如果我有下一个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
答案 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。