为了更好地理解列表中的理解,我到处玩弄,结果遇到了一些我无法解释的意外结果。我以前没发现有人问这个问题,但如果是重复问,我很抱歉。
我基本上是想写一个生成生成器的生成器。使用列表理解的简单生成器如下所示:
(x for x in range(10) if x%2==0) # generates all even integers in range(10)
我试图写一个生成两个生成器的生成器,第一个生成器生成范围(10)内的偶数,第二个生成器生成范围(10)内的奇数。为此,我做到了:
>>> (x for x in range(10) if x%2==i for i in range(2))
<generator object <genexpr> at 0x7f6b90948f00>
>>> for i in g.next(): print i
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
UnboundLocalError: local variable 'i' referenced before assignment
>>> g.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> g = (x for x in range(10) if x%2==i for i in range(2))
>>> g
<generator object <genexpr> at 0x7f6b90969730>
>>> g.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
UnboundLocalError: local variable 'i' referenced before assignment
我不明白为什么“我”会在作业前被提及
我想这可能和i in range(2)
有关,所以我做了:
>>> g = (x for x in range(10) if x%2==i for i in [0.1])
>>> g
<generator object <genexpr> at 0x7f6b90948f00>
>>> g.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
UnboundLocalError: local variable 'i' referenced before assignment
这对我来说毫无意义,所以我想最好先尝试一些更简单的方法。所以我回到清单上,试着:
>>> [x for x in range(10) if x%2==i for i in range(2)]
[1, 1, 3, 3, 5, 5, 7, 7, 9, 9]
我希望它和:
>>> l = []
>>> for i in range(2):
... for x in range(10):
... if x%2==i:
... l.append(x)
...
>>> l
[0, 2, 4, 6, 8, 1, 3, 5, 7, 9] # so where is my list comprehension malformed?
但当我凭直觉尝试的时候,这个方法奏效了:
>>> [[x for x in range(10) if x%2==i] for i in range(2)]
[[0, 2, 4, 6, 8], [1, 3, 5, 7, 9]] # so nested lists in nested list comprehension somehow affect the scope of if statements? :S
所以我想这可能是if
语句在什么级别的作用域中工作的问题。所以我试了一下:
>>> [x for x in range(10) for i in range(2) if x%2==i]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
现在我完全糊涂了。有人能解释一下这种行为吗。我不明白为什么我的列表理解似乎格式不正确,也不明白if
语句的作用域是如何工作的。
注:当我校对这个问题的时候,我意识到这看起来确实有点像家庭作业问题,其实不是。
您需要使用一些括号:
这是因为以前的列表理解将i变量泄漏到封闭范围,并成为当前范围的i。尝试启动一个新的python解释器,但由于NameError而失败。在Python 3中,计数器的泄漏行为已被删除。
编辑:
等效for循环:
将是:
这也会导致名称错误。
编辑2:
带圆括号的版本:
相当于:
Lie Ryan的for loop等价物让我想到了下面这一点,它看起来确实工作得很好:
输出
对莱恩的回答进行了一些扩展:
某物=(如果x%2==i,则x代表x,范围(10)内的x)
相当于:
而括号内的版本相当于:
这实际上产生了两个生成器:
不幸的是,它产生的发电机有些不稳定,因为输出将取决于您如何使用它们:
我的建议是完整地编写生成器函数:我认为不这样做就试图获得对
i
的正确作用域可能几乎是不可能的。相关问题 更多 >
编程相关推荐