为了账号安全,请及时绑定邮箱和手机立即绑定

高级嵌套列表理解语法

高级嵌套列表理解语法

慕的地6264312 2019-11-28 12:41:43
我一直在与列表理解打交道,以更好地理解它们,但遇到了一些我无法解释的意外输出。我之前没有发现这个问题,但是,如果它是重复的问题,我深表歉意。我本质上是想写一个生成器。一个使用列表推导的简单生成器如下所示:(x for x in range(10) if x%2==0) # generates all even integers in range(10)我想要做的是编写一个生成器,生成两个生成器-第一个生成器生成range(10)中的偶数,第二个生成range(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>我不明白为什么在分配之前会引用“ i”我认为它可能与有关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语句范围界定的工作原理。
查看完整描述

3 回答

?
LEATH

TA贡献1936条经验 获得超6个赞

您需要使用一些括号:


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

这对我来说没有意义,所以我认为最好先尝试一些简单的方法。因此,我返回列表并尝试:


[>>> [x对于范围(2)中的i,如果x%2 == i,则x对于范围(10)中的x] [1、1、3、3、3、5、5、7、7、9、9]


之所以有效,是因为先前的列表理解将i变量泄漏到了封闭范围,并成为当前变量的i。尝试启动一个新的python解释器,由于NameError失败,这将失败。计数器的泄漏行为已在Python 3中删除。


编辑:


等效于for的循环:


(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)

这也会给出名称错误。


编辑2:


括号中的版本:


((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)


查看完整回答
反对 回复 2019-11-28
?
人到中年有点甜

TA贡献1895条经验 获得超7个赞

Lie Ryan的for循环等效项将我带到以下内容,这似乎确实可以正常工作:


[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]Lie Ryan的for循环等效项将我带到以下内容,这似乎确实可以正常工作:


[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]


查看完整回答
反对 回复 2019-11-28
?
青春有我

TA贡献1784条经验 获得超8个赞

扩大李·瑞安的答案:


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


等效于:


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>]

不幸的是,它产生的生成器有些不稳定,因为输出将取决于您如何使用它们:


>>> gens = ((x for x in range(10) if x%2==i) for i in range(2))

>>> for g in gens:

        print(list(g))


[0, 2, 4, 6, 8]

[1, 3, 5, 7, 9]

>>> gens = ((x for x in range(10) if x%2==i) for i in range(2))

>>> for g in list(gens):

        print(list(g))


[1, 3, 5, 7, 9]

[1, 3, 5, 7, 9]

我的建议是完全写出生成器函数:我认为,如果i不这样做就试图获得正确的作用域几乎是不可能的。


查看完整回答
反对 回复 2019-11-28
  • 3 回答
  • 0 关注
  • 428 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号