Я смотрел это видео Объектно-ориентированное программирование - это плохо .Тема не имеет отношения к вопросу, который я задам, но видео приводит к этому.Точно, в 41:10
он говорит о функции, которой, кажется, нет в python, он говорит о способности иметь вложенные функции / блоки, которые не знают о полном локальном контексте, но вместо этого, знают о некоторых переменныхвыбрано вручную.По сути, он просит о возможности удалить / частично скрыть окружение от замыкания.
Вот как должна выглядеть нужная функция в python (например, с использованием use
декоратора):
def foo():
x, y, z = 1, 2, 3
def baz():
print(x, y) # prints "1 2"
@use(y)
def bar():
print(y) # Should print "2"
z = 4 # Should create a local variable named `z`
print(x) # Should raise a NameError (`x` not defined)
bar(), baz())
foo()
Я пытался реализовать этот декоратор, но безуспешно, поэтомуЯ попытался сделать это с более простой целью: не скрыть частично среду, а полностью ее скрыть.Вот решение, которое я нашел:
import ctypes
def foo():
x, z = 1
def baz():
print(x) # prints 1
@hide_environment
def bar(y):
print(y) # prints 2
z = 3
print(z) # prints 3
print(x) # NameError is raised
baz(), bar(2)
def hide_environment(f):
def environment_agnostic_f(*args, **kwargs):
remove_environment(f)
return f(*args, **kwargs)
return environment_agnostic_f
def remove_environment(f):
if f.__closure__ is None:
return
for v in f.__closure__:
py_obj = ctypes.py_object(v)
ctypes.pythonapi.PyCell_Set(py_obj, None) # that look like it could go wrong
foo()
У меня есть четыре вопроса:
- Уже существует в python?
- Возможно ли реализовать
use
механизм, описанный в видео (внутри python)? - Правильно ли реализована моя реализация
hide_environment
?
Я не понимаю, как 2. возможно, так как у меня нетидея, если возможно перехватить / или найти адрес ячейки, в который было помещено значение y
.Я не уверен, что понимаю, как это делается, но из того, что я понимаю, когда читается foo
, «компилятор» (не уверен, стоит ли так его называть) помещает все locals
из * 1028.* в __closure__
объектах, на которые позже будут ссылаться bar
и baz
.Это привело к моему последнему вопросу:
Есть ли где-нибудь в документации, где описывается способ закрытия?