Ответ 1
Помните, что на уровне модуля глобальные и локальные языки являются одним и тем же словарем. Если
exec
получает два отдельных объекта как глобальные и локальные, код будет выполнен так, как если бы он был встроен в определение класса.
Вы прошли в двух отдельных словарях, но попытались выполнить код, который требует наличия глобальных глобальных возможностей. import math
в классе создаст атрибут локальной области, и создаваемая вами функция не сможет получить доступ к этому, поскольку имена классов классов не рассматриваются для закрытия функций.
См. Именование и привязка в ссылке на модель исполнения Python:
Блоки и аргументы определения класса
exec()
иeval()
являются особыми в контексте разрешения имен. Определение класса - это исполняемый оператор, который может использовать и определять имена. Эти ссылки следуют нормальным правилам разрешения имен, за исключением того, что в глобальном пространстве имен просматриваются несвязанные локальные переменные. Пространство имен определения класса становится атрибутом словаря класса. Объем имен, определенных в блоке класса, ограничен блоком класса; он не распространяется на кодовые блоки методов [.]
Вы можете воспроизвести ошибку, выполнив код в определении класса:
>>> class Demo:
... import math
... def func(x):
... return math.sin(x)
... func(10)
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in Demo
File "<stdin>", line 4, in func
NameError: name 'math' is not defined
Просто перейдите в один словарь.