Расширенный синтаксис понимания вложенных списков

Я играл со списками, чтобы лучше понять их, и натолкнулся на некоторые неожиданные результаты, которые я не могу объяснить. Я не нашел, чтобы этот вопрос задавался раньше, но если это / повторяется, прошу прощения.

По сути, я пытался написать генератор, который генерировал генераторы. Простой генератор, использующий понимание списка, будет выглядеть так:

(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' упоминается перед присваиванием

Я думал, что это могло иметь какое-то отношение к i в диапазоне (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

Так что я подумал, что это может быть проблема с каким уровнем of scope работает оператор 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 .

PS: Во время корректуры вопроса я понял, что это действительно выглядит немного как вопрос домашнего задания - это не так.

42
задан martineau 9 June 2018 в 16:15
поделиться