高级嵌套列表理解语法 [英] Advanced Nested List Comprehension Syntax

查看:91
本文介绍了高级嵌套列表理解语法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试使用列表理解来更好地理解它们,但遇到了一些我无法解释的意外输出.我以前没有问过这个问题,但是如果它是重复的问题,我表示歉意.

I was playing around with list comprehensions to get a better understanding of them and I ran into some unexpected output that I am not able to explain. I haven't found this question asked before, but if it /is/ a repeat question, I apologize.

我本质上是在尝试编写一个生成器.一个使用列表推导的简单生成器如下所示:

I was essentially trying to write a generator which generated generators. A simple generator that uses list comprehension would look like this:

(x for x in range(10) if x%2==0) # generates all even integers in range(10)

我想要做的是编写一个生成器,该生成器生成两个生成器-第一个生成器生成range(10)中的偶数,第二个生成range(10)中的奇数.为此,我做到了:

What I was trying to do was write a generator that generated two generators - the first of which generated the even numbers in range(10) and the second of which generated the odd numbers in range(10). For this, I did:

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

I don't understand why 'i' is being referenced before assignment

我认为可能与i in range(2)有关,所以我这样做了:

I thought it might have had something to do with i in range(2), so I did:

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

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

This didn't make sense to me, so I thought it best to try something simpler first. So I went back to lists and tried:

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

但是当我直觉尝试时,它起作用了:

But when I tried it on a hunch, this worked:

>>> [[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语句的作用域范围可能是一个问题.因此,我尝试了此操作:

So I thought it might be a problem with what level of scope the if statement operates in. So I tried this:

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

And now I'm thoroughly confused. Can someone please explain this behavior. I don't understand why my list comprehensions seem to be malformed, nor do I understand how the scoping of the if statements work.

PS:在对问题进行校对时,我意识到这确实有点像作业问题-并非如此.

PS: While proof-reading the question, I realized that this does look a bit like a homework question - it is not.

推荐答案

您需要使用一些括号:

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

这对我来说没有意义,所以我 认为最好尝试一些东西 首先更简单.所以我回到清单 并尝试:

This didn't make sense to me, so I thought it best to try something simpler first. So I went back to lists and tried:

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

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

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

That worked because a previous list comprehension leaks the i variable to the enclosing scope, and become the i for the current one. Try starting a fresh python interpreter, and that would fail due to NameError. The counter's leaking behavior has been removed in 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)

这也会给出名称错误.

带括号的版本:

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

这篇关于高级嵌套列表理解语法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆