我有一些东西,当作为列表理解运行时,运行正常。
看起来像,
[myClass().Function(things) for things in biggerThing]
Function
是一种方法,它会构建一个列表。该方法本身不会返回任何内容,但是列表会被操作。
现在当我将其更改为生成器时,
(myClass().Function(things) for things in biggerThing)
它不像我期望的那样操纵数据。事实上,它似乎根本没有操纵它。
列表理解和生成器之间的功能区别是什么?
答案 0 :(得分:5)
生成器会在消耗时进行动态评估。因此,如果您从不迭代生成器,则永远不会评估其元素。
所以,如果你这样做了:
for _ in (myClass().Function(things) for things in biggerThing):
pass
Function
会运行。
现在,你的意图在这里并不清楚。
相反,请考虑使用map
:
map(myClass().Function, biggerThing)
请注意,这将始终使用MyClass的相同实例
如果这是一个问题,那么请执行:
for things in BiggerThing:
myClass().Function(things)
答案 1 :(得分:3)
生成器是lazy evaluated。您需要处理生成器以便评估您的功能。可以使用collections.deque
来使用生成器:
import collections
generator = (myClass().Function(thing) for thing in biggerThing)
collections.deque(generator , maxlen=0)
并考虑使用@staticmethod
或@classmethod
,或更改为
myfunc = myClass().Function
generator = (myfunc(thing) for thing in biggerThing)
collections.deque(generator , maxlen=0)
为每个myClass
处理减少thing
创建的新实例。
更新,效果
collections
vs iteration
def l(): for x in range(100): y = x**2 yield y def consume(it): for i in it: pass >>> timeit.timeit('from __main__ import l, consume; consume(l())', number=10000) 0.4535369873046875 >>> timeit.timeit('from __main__ import l, collections; collections.deque(l(), 0)', number=10000) 0.24533605575561523
class Test(object): @staticmethod def stat_pow(x): return x**2 @classmethod def class_pow(cls, x): return x**2 def inst_pow(self, x): return x**2 def static_gen(): for x in range(100): yield Test.stat_pow(x) def class_gen(): for x in range(100): yield Test.class_pow(x) def inst_gen(): for x in range(100): yield Test().inst_pow(x) >>> timeit.timeit('from __main__ import static_gen as f, collections; collections.deque(f(), 0)', number=10000) 0.5983021259307861 >>> timeit.timeit('from __main__ import class_gen as f, collections; collections.deque(f(), 0)', number=10000) 0.6772890090942383 >>> timeit.timeit('from __main__ import inst_gen as f, collections; collections.deque(f(), 0)', number=10000) 0.8273470401763916
答案 2 :(得分:2)
创建生成器时,您只能使用一次元素。这就像我正在创造一批我正在吃的饼干。他们服务于他们的目的(让我开心),但是一旦你使用它们就会消失。
列表推导创建列表,它们将允许您永久地(表面上)访问该数据结构。您还可以使用它们上的所有列表方法(非常有用)。但这个想法是它创建了一个实际的数据结构(为你保存数据的东西)。
答案 3 :(得分:1)
生成器将不会执行该功能,直到您在生成器上调用next()
。
>>>def f():
... print 'Hello'
>>>l = [f() for _ in range(3)]
Hello
Hello
Hello
>>>g = (f() for _ in range(3)) # nothing happens
>>>
>>>next(g)
Hello
答案 4 :(得分:0)
列表理解:
列表可以编入索引。
例如。,。 [0, 1, 2, 3, 4][0]
创建的列表可以使用任意次。
空列表占用72个字节,每个项目添加占用8个字节。
发生器:
生成器无法编入索引
生成器只能使用一次。
生成器占用的内存要少得多(80字节)。
请注意,对于生成器,一旦使用它,内部的内容就会被清空。
>>> sys.getsizeof([])
72
>>> list1 = [x for x in range(0, 5)]
>>> sys.getsizeof(list1)
136
>>>
>>> generator1 = (x for x in range(0,100))
>>> sys.getsizeof(generator1)
80
>>> generator1 = (x for x in range(0,5))
>>> sys.getsizeof(generator1)
80
>>> list(generator1)
[0, 1, 2, 3, 4]
>>> list(generator1)
[]
>>>