Из того, что я понял, документация действительно немного неоднозначна по свободным переменным. Существуют свободные глобальные переменные , которые рассматриваются как простые глобалы и лексически связанные свободные переменные . Эли Бендерски суммирует это в блоге в столбце символа :
К сожалению, в ядре Python есть стенография, которая может изначально запутать читателей относительно того, что именно представляет собой «свободную» переменную. К счастью, это очень легкая путаница, которую легко привести в порядок. Ссылка на модель исполнения говорит:
Если переменная используется в кодовом блоке, но не определена там, это свободная переменная.
blockquote>Это согласовано с формальным определением . В источнике, однако, «свободный» фактически используется как сокращенное выражение для «лексически связанной свободной переменной» (т.е. переменные, для которых привязка найдена в охватывающей области), причем «глобальный» используется для обозначения всех оставшихся свободных переменные. Поэтому, читая исходный код CPython, важно помнить, что полный набор свободных переменных включает как переменные, помеченные как «свободные», так и те, которые помечены как «глобальные».
Таким образом, для избегайте путаницы, я говорю «лексически связан», когда я хочу ссылаться на переменные, которые фактически обрабатываются в CPython как свободные.
blockquote>(выделение мое)
Причина, по которой это стенография была, вероятно, потому, что, когда у вас есть глобальная свободная переменная , в выпуске байт-кода не происходит никаких изменений. Если переменная
global
является «свободной» или если она не изменяет тот факт, что поиск этого имени будет использоватьLOAD_GLOBAL
в обоих случаях. Таким образом, глобальные свободные переменные не все таковы.С другой стороны, лексически связанные переменные обрабатываются специально и заключены в объекты
cell
, объекты - это хранилище пространство для лексически связанных свободных переменных и находятся в атрибуте__closure__
для данной функции. Для них создается специальная командаLOAD_DEREF
, которая исследует ячейки, присутствующие для свободных переменных. Описание для командыLOAD_DEREF
:
LOAD_DEREF(i)
Загружает ячейку, содержащуюся в слоте i ячейки и свободной памяти переменных
blockquote>Таким образом, свободные переменные Python имеют значение только как понятие в ситуациях, когда определение для объекта, имеющего состояние, лексически (т.е. статически) вложено в другое определение для объекта, имеющего состояние.