Я играл со списками, чтобы лучше понять их, и натолкнулся на неожиданный вывод, который я не в состоянии объяснить. Я не нашел этот вопрос, заданный ранее, но если это / является / повторный вопрос, я прошу прощения.
Я пытался написать генератор, который генерировал генераторы. Простой генератор, использующий понимание списка, будет выглядеть так:
(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 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
.
PS: читая вопрос, я понял, что это немного похоже на домашнее задание - это не так.