Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 高级嵌套列表理解语法_Python_Syntax_Scope_List Comprehension - Fatal编程技术网

Python 高级嵌套列表理解语法

Python 高级嵌套列表理解语法,python,syntax,scope,list-comprehension,Python,Syntax,Scope,List Comprehension,为了更好地理解它们,我在玩列表理解游戏,结果遇到了一些我无法解释的意外输出。我以前没有发现有人问过这个问题,但如果是重复的问题,我道歉 我基本上是想写一个生成生成器的生成器。使用列表理解的简单生成器如下所示: (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==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
这对我来说没有意义,所以我认为最好先尝试一些简单的方法。因此,我回到列表并尝试:

>>> [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
所以我认为如果语句在什么级别的范围内运行,这可能是个问题。所以我试了一下:

>>> [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
语句的作用域是如何工作的


PS:在校对问题时,我意识到这看起来确实有点像家庭作业问题——事实并非如此。

你需要使用一些括号:

((x for x in range(10) if x%2==i) for i in range(2))
这对我来说没有意义,所以我 我觉得最好尝试一下 先简单一点。所以我又回到清单上 并尝试:

>>> [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]
[>>>[x表示范围(10)内的x,如果x%2==i表示范围(2)内的i] [1,1,3,3,5,5,7,7,9,9]

这是因为以前的列表理解将i变量泄漏到封闭范围,并成为当前变量的i。请尝试启动新的python解释器,但由于NameError而失败。在python 3中,计数器的泄漏行为已被删除

编辑:

循环的等效值为:

(x for x in range(10) if x%2==i for i in range(2))
将是:

l = []
for x in range(10):
    if x%2 == i:
        for i in range(2):
            l.append(x)
这也给出了一个名称错误

EDIT2:

括号内的版本:

((x for x in range(10) if x%2==i) for i in range(2))
相当于:

li = []
for i in range(2):
    lx = []
    for x in range(10):
        if x%2==i:
            lx.append(x)
    li.append(lx)
def _gen1():
    for x in range(10):
        if x%2 == i:
            for i in range(2):
                yield x
something = _gen1()
def _gen1():
    def _gen2():
        for x in range(10):
            if x%2 == i:
                yield x

    for i in range(2):
        yield _gen2()
something = _gen1()

Lie给出了语法问题的答案。一个建议:不要在生成器的主体中插入太多内容。函数更具可读性

def make_generator(modulus):
    return (x for x in range(10) if x % 2 == modulus)
g = (make_generator(i) for i in range(2))

稍微扩展一下Lie Ryan的回答:

某物=(如果x%2==i表示范围(2)中的i,则x表示范围(10)中的x)

相当于:

li = []
for i in range(2):
    lx = []
    for x in range(10):
        if x%2==i:
            lx.append(x)
    li.append(lx)
def _gen1():
    for x in range(10):
        if x%2 == i:
            for i in range(2):
                yield x
something = _gen1()
def _gen1():
    def _gen2():
        for x in range(10):
            if x%2 == i:
                yield x

    for i in range(2):
        yield _gen2()
something = _gen1()
而括号内的版本相当于:

li = []
for i in range(2):
    lx = []
    for x in range(10):
        if x%2==i:
            lx.append(x)
    li.append(lx)
def _gen1():
    for x in range(10):
        if x%2 == i:
            for i in range(2):
                yield x
something = _gen1()
def _gen1():
    def _gen2():
        for x in range(10):
            if x%2 == i:
                yield x

    for i in range(2):
        yield _gen2()
something = _gen1()
这实际上产生了两个发电机:

[<generator object <genexpr> at 0x02A0A968>, <generator object <genexpr> at 0x02A0A990>]

我的建议是完整地写出生成器函数:我认为不这样做就试图在
I
上获得正确的作用域几乎是不可能的。

Lie Ryan的for loop等价物将我引向以下几点,这似乎很好:

[x for i in range(2) for x in range(10) if i == x%2]
输出

[0, 2, 4, 6, 8, 1, 3, 5, 7, 9]

[x代表范围内的x(10)如果x%2==i代表范围内的i(2)]
有效吗?我得到了
名称错误:名称“i”没有定义
(Python 2.6.2)@ManojGovindan:我得到了你得到的(Python 2.6.5)相关信息:谢谢,我理解泄漏错误,但为什么需要括号?没有括号的代码翻译成什么(就for循环而言)?我知道括号解决了这个问题,我只是不明白为什么幸运的是,根据您使用结果的方式,第一个生成器可以给出偶数、奇数,或者一些偶数,然后是一些奇数。@asmoore82:它没有改变,它总是返回一个生成器。它只是处于“等价”状态版本中,我先发制人地展开了生成器以使事情更容易理解。哦,哇,谢谢你的回复,我删除了我的评论,因为我误读了OP特别要求生成生成器谢谢。我理解这一点,我确实更喜欢这一点。但我试图通过列表理解进行一些练习,看看我能做多少d按下按钮为什么将生成器包装在
list()
中会导致它从1开始而不是从0开始?(我用更多的生成器进行了测试,看起来生成器都在做相同的事情)当被消耗时,生成器总是做同样的事情:它们给你数字,其中
x%2==i
。第一种方法将
i
设置为
0
然后生成一个生成器,该生成器被消耗以给出偶数,然后
i
变为1,另一个生成器返回给你奇数,注意:这是相同的
i
每次仅使用不同的值。使用
list(gens)
意味着两台发电机都是这样创建的,
i
在您使用任何一台发电机之前被设置为
1
。为什么在第一种情况下,
i
不共享?哦。我想这是因为
i
总是共享的,但是在第一种情况下,发电机与外回路串联运行,而在第二种情况下,
i
是共享的e发电机在外回路完成后运行,因此它们都得到i的最终值。为什么
i
不是副本,即发电机的作用类似于闭包?