Мое понимание области видимости в python 2 (я только что перешел на python 3) заключалось в том, что a не следует определять в run (), а a2 есть.
И a
, и a2
видны изнутри run
. a
определяется в глобальной области видимости, поэтому он виден везде в этом файле.
Я ожидал, что если test5 будет работать нормально, то test6 и test7 также будут в порядке.
В 3.X списочные представления получают свою собственную область. Понимание списка test6 имеет доступ к трем областям: область действия списка, область функции и глобальная область. Таким образом, он имеет доступ к i
и a2
и a
.
По умолчанию код, выполняемый внутри eval
, имеет доступ к двум областям: глобальной области и ближайшей локальной области. Это означает, что test7
eval может обращаться к переменным, определенным на уровне файла, и он может обращаться к переменным, определенным внутри понимания списка, но он не может обращаться к переменным, определенным внутри функции, но вне понимания списка. Он может видеть a
и i
, но не a2
.
В 2.7 списочные представления не имеют собственной области видимости. Они имеют ту же область видимости, что и функция, в которой они определены. Это объясняет, почему ваш код выполняется в 2.7, а не в 3.X. IIRC, это единственное изменение в системе прицела между 2.7 и 3.X. (а если нет, то это единственное изменение, которое имеет отношение к этому сценарию.)