def outer():
n = 1
def inner():
return n
n = 2
return inner
inner = outer()
print innner() # output 2
Я хорошо знаю, что, как CPython реализует замыкание, мой вопрос не в том, почему вывод равен 2, а в том, почему Python создает вывод 2 .
Python использует объект ячейки во внедрении замыкания, который косвенно ссылается именно на PyObject, который мы хотим захватить. PythonVM создает ровно один объект ячейки для одного freevar, в этом примере во внешней области видимости объекта ячейки сначала ref 1, а затем ref 2. Когда мы вызываем внутреннюю функцию, freevar всегда загружает самое новое значение во внешней функции, поэтому выводим 2.
«Объект ячейки» - это дополнительный абстрактный уровень в реализации замыкания. На самом деле я изменил несколько строк кода CPython о процессе кода STORE_DEREF и LOAD_DEREF, удалил уровень «объекта ячейки», сохранил реальный объект во внутреннем закрытии. Тогда пример выдаст 1. Все работает нормально, кроме простой трассировки в стандартной библиотеке, в некотором коде предполагается, что ячейка является хэшируемой. Но я думаю, что это не имеет большого значения.
Я думаю, что вывод "1" - это интуитивный смысл. Итак, мой вопрос: почему Python делает уровень «объект-ячейка» в реализации замыкания? Я четко знаю реализацию, но почему такой дизайн Python?