希望a如果是单个元素而非可迭代对象,就重复a组成长度和b相同的生成器(其实可以用list,不过那样就没这篇文章了),每个元素都是本来的a相同,比如a=1的话,结果就是即[1,1,1,1,1,..]这样。
按直观想法写了类似如下的代码(不知道大家有没有也遇到过):
a = (a for _ in b)
测试一下,不对劲:
>>> a = 1 >>> a = (a for _ in range(5)) >>> for e in a: ... print(e) ... <generator object <genexpr> at 0x000001676357CB30> <generator object <genexpr> at 0x000001676357CB30> <generator object <genexpr> at 0x000001676357CB30> <generator object <genexpr> at 0x000001676357CB30> <generator object <genexpr> at 0x000001676357CB30>
!试一试把a换成1:
>>> a = (1 for _ in range(5)) >>> for e in a: ... print(e) ... 1 1 1 1 1
嗯这就是惰性求值了,如 a = (a for _ in range(5)) 这样的表达,求值前a已经是个迭代器而不是1了,next(a)结果为a本身,输出a内的元素和输出a本身一样:
>>> for e in a: ... print(a) ... <generator object <genexpr> at 0x000001676357CB30> <generator object <genexpr> at 0x000001676357CB30> <generator object <genexpr> at 0x000001676357CB30> <generator object <genexpr> at 0x000001676357CB30> <generator object <genexpr> at 0x000001676357CB30>
那么手动让他勤快点呢:
>>> a = (next(a) for _ in range(5)) >>> next(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 1, in <genexpr> ValueError: generator already executing
禁止套娃XD
生成器中for部份本身没有惰性求值,他们虽然都叫a,但for内的a和左边的a运行的时候已经不是一个a了。合理.jpg
>>> a = 1 >>> a = (a for _ in a) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not iterable
>>> a = range(3) >>> a = ((i,a) for i in a) >>> for e in a: ... print(e) ... (0, <generator object <genexpr> at 0x00000167636924A0>) (1, <generator object <genexpr> at 0x00000167636924A0>) (2, <generator object <genexpr> at 0x00000167636924A0>)
不过如果for包含了生成器,生成器部份的变量还是会惰性求值
>>> a = range(3) >>> a range(0, 3) >>> a = ((i,a) for i in a) >>> a <generator object <genexpr> at 0x000001676357CB30> >>> a = ((i,a) for i in a) >>> a <generator object <genexpr> at 0x00000167636929E0> >>> for e in a: ... print(e) ... ((0, <generator object <genexpr> at 0x00000167636929E0>), <generator object <genexpr> at 0x00000167636929E0>) ((1, <generator object <genexpr> at 0x00000167636929E0>), <generator object <genexpr> at 0x00000167636929E0>) ((2, <generator object <genexpr> at 0x00000167636929E0>), <generator object <genexpr> at 0x00000167636929E0>)
迭代时,第二个表达式的for中迭代的a是第一次的生成器表达式,第二次的生成器表达式还未成型时,for就固定迭代器地址为第一次的生成器表达式,而第一个式子中(i,a)的a是惰性求值的,值为第二次的生成器表达式
差不多了,已经晕了,如果哪里有误或者bug,那太正常了,欢迎大家指正,也欢迎更多的讨论。其实写完感觉听浅显的,看着看着有即视感了,但是不记得在那看过类似的例子。如果有见过的大佬求帮帮!