Ответ 1
В Python 3, у понятий списка есть своя область, которая следует тем же правилам, что и область функций. Вы знаете, как методы класса автоматически не заглядывают в область класса для поиска переменных?
class Example:
var = 1
def this_fails(self):
print(var)
Example().this_fails() # NameError
То же самое относится к любой области возможностей, вложенной внутри области видимости класса, включая область охвата списка. Поиск cl2
внутри понимания списка обходит область видимости класса и переходит прямо к глобальным. Он эффективно работает следующим образом:
class Foo(object):
...
def make_cc(outer_iterable):
result = []
for i1 in outer_iterable:
for i2 in cl2: # This fails
result.append(i1 + i2)
return result
cc = make_cc(cl1) # cl1 is evaluated outside the comprehension scope, for reasons
Обратите внимание, что поиск cl1
работает отлично, потому что это происходит в классе, вне понимания, несмотря на синтаксическое вложение внутри понимания. Они приняли это решение, когда Python представил genexps, потому что раньше он обнаружил несколько общих ошибок genexp. Именно поэтому работают функции cc1
и cc2
; их единственное использование переменных уровня класса находится в их внешнем (только) for
итерабельном.
Использование понятий и выражений генератора внутри оператора класса - беспорядок. Это не должно быть, но это так. Придерживайтесь регулярных циклов или запускайте выражения вне выражения класса, чтобы семантика была более очевидной.