列出具有不同语句的理解示例

时间:2014-09-29 09:12:47

标签: python list-comprehension

如果我有下一个for-loop

a = 0
b = [1,2,3]

for x in b:
    print a + x
    a = x

是否可以在列表理解中覆盖它?我的第一次尝试失败了:

a = 0
b = [1,2,3]
[[print a+x, a=x] for x in b]

    [[print a+x, a=x] for x in b]
          ^
SyntaxError: invalid syntax

3 个答案:

答案 0 :(得分:4)

有很多方法可以将其写为列表理解,但你真的不应该这样做。理解是针对面向表达式的编程,循环是针对副作用的。

答案 1 :(得分:2)

正如larsmans所说,你真的不应该这样做。使用副作用的疯狂列表理解更难以阅读和阅读。理解比表现良好的自足的。

但是如果你仍然好奇,那么这就是各种方法之一。它利用可变的默认函数参数来保存状态。

def adder(x, last=[]):
    if last == []:
        last.append(0)
    last[0] += x
    return last[0]

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

显然,这比for循环更冗长,更难阅读,我敢说它的效率也低得多。它依赖于Python的一个特性(可变默认函数参数的行为),这是新Python程序员不易理解的(许多有经验的Python程序员也不会特别满意)。

所以不要在代码中使用这种疯狂!


修改

以下是一些使用列表推导来做这种邪恶事情的方法。

首先,在序列的切片副本上使用sum可怕的低效方式:

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

类似的丑陋,这一次是使用reduce。 Guido在最好的时候讨厌reduce,所以我讨厌想象他对这种怪物的看法。 :)

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

还有一些我前一段时间设计的,其中两个使用函数属性来保存状态,最后一个使用类来保存状态,这可能是最不讨厌的方法。

#! /usr/bin/env python

''' Create an accumulator function from a 2 arg function.
    Like a cross between map() & reduce().
'''

def acc0(func, v0=0):
    def f(v):
        f.v = func(f.v, v)
        return f.v
    f.v = v0
    return f


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

    f.v = v0
    return f


class acc2(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


def test(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 = 10
    print [f(i) for i in xrange(1,12)]

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

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


def main():
    for acc in (acc0, acc1, acc2):
        test(acc)
        print


if __name__ == '__main__':
    main()

答案 2 :(得分:1)

您不能在列表理解中使用print。你应该保持for-loop。