Skip to content Skip to sidebar Skip to footer

List Comprehension Example With Different Statements

If I have next for-loop a = 0 b = [1,2,3] for x in b: print a + x a = x is it possible to overwrite it in the list comprehension? My first attempt is fail: a = 0 b = [1,2

Solution 1:

There are ways to write this as a list comprehension, but you really shouldn't. Comprehensions are for expression-oriented programming, loops are for side-effects.

Solution 2:

As larsmans said, you really shouldn't do this. Crazy list comprehensions that use side effects are even harder to read & understand than well-behaved self-contained ones.

But if you're still curious, here's one of the various ways to do it. It utilises a mutable default function parameter to save state.

def adder(x, last=[]):
    iflast == []:
        last.append(0)
    last[0] += xreturnlast[0]

b = (1, 2, 3, 4)
print [adder(x) forx in b]

Clearly, this is more verbose and harder to read than the for loop, and I dare say it's also much less efficient. And it relies on a feature of Python (the behaviour of mutable default function parameters) that is not easy to understand by new Python programmers (and many experienced Python programmers aren't particularly happy with, either).

So please don't use this kind of craziness in your code!


Edit

Here are a few more ways to do this sort of evil thing with list comprehensions.

Firstly, a horribly inefficient way that uses sum on sliced copies of the sequence:

b = (10, 20, 30, 40)
[sum(b[:1+i]) for i in xrange(len(b))]

A similar piece of ugliness, this time using reduce. Guido hates reduce at the best of times, so I hate to imagine what he'd think of this monstrosity. :)

b = (10, 20, 30, 40)
reduce(lambda s,x: s + [s[-1] + x], b, [0])[1:]

And here are a few more that I devised a while ago, two using function attributes to save state, and finally one that saves state using a class, which is probably the least obnoxious way to do it.

#! /usr/bin/env python''' Create an accumulator function from a 2 arg function.
    Like a cross between map() & reduce().
'''defacc0(func, v0=0):
    deff(v):
        f.v = func(f.v, v)
        return f.v
    f.v = v0
    return f


defacc1(func, v0=0):
    deff(v, c=None): 
        if c!=None: 
            f.v = c
        f.v = func(f.v, v)
        return f.v

    f.v = v0
    return f


classacc2(object):
    def__init__(self, func, value=0):
        self.v = value
        self.func = func

    def__call__(self, x):
        self.v = self.func(self.v, x)
        return self.v


deftest(acc):
    g = acc(lambda u,v: u+v)
    print [g(i) for i in xrange(1,12)]

    f = acc(lambda u,v: u*v, 1)
    print [f(i) for i in xrange(1,12)]
    f.v = 10print [f(i) for i in xrange(1,12)]

    f.v = 1print [f(i) for i in xrange(1,15)]
    f.v = 2print [f(i) for i in xrange(1,12)]

    g.v = 0print [g(i) for i in xrange(1,12)]
    g.v = 100print [g(i) for i in xrange(1,12)]


defmain():
    for acc in (acc0, acc1, acc2):
        test(acc)
        printif __name__ == '__main__':
    main()

Solution 3:

You may not use print in a list comprehension. You should keep the for-loop instead.

Post a Comment for "List Comprehension Example With Different Statements"