Почему я не могу получить доступ к встроенным функциям, если я использую пользовательский dict в качестве глобала функции? - PullRequest
0 голосов
/ 30 мая 2018

У меня есть подкласс dict, подобный этому:

class MyDict(dict):
    def __getitem__(self, name):
        return globals()[name]

Этот класс можно использовать с eval и exec без проблем:

>>> eval('bytearray', MyDict())
<class 'bytearray'>
>>> exec('print(bytearray)', MyDict())
<class 'bytearray'>

Но если я создаю экземпляр объекта функции с помощью конструктора types.FunctionType, функция не может получить доступ к встроенным функциям:

import types

func = lambda: bytearray
func_copy = types.FunctionType(func.__code__,
                              MyDict(),
                              func.__name__,
                              func.__defaults__,
                              func.__closure__)

print(func_copy())
# Traceback (most recent call last):
#   File "untitled.py", line 16, in <module>
#     print(func_copy())
#   File "untitled.py", line 8, in <lambda>
#     func = lambda: bytearray
# NameError: name 'bytearray' is not defined

Замена MyDict() с globals() или dict(globals()) или событием {'__builtins__': __builtins__} код печатается <class 'bytearray'>, как и ожидалось.

Я не понимаю, откуда это исключение.Кто-нибудь может объяснить это поведение?Почему он работает с eval, а не с функциональным объектом?

1 Ответ

0 голосов
/ 07 июня 2018

Не полный ответ, но, похоже, происходит то, что CPython игнорирует пользовательский __getitem__ при доступе к встроенным функциям.Кажется, к MyDict относятся как к обычному (не подклассу) диктову.Если ключ '__builtins__' действительно присутствует в dict, то все работает правильно:

class MyDict(dict):
    def __getitem__(self, name):
        return globals()[name]


import types

globs = MyDict()
globs['__builtins__'] = __builtins__

func = lambda: bytearray
func_copy = types.FunctionType(func.__code__,
                              globs,
                              func.__name__,
                              func.__defaults__,
                              func.__closure__)

print(func_copy())
# output: <class 'bytearray'>

Остается вопрос, почему это происходит только с FunctionType, а не с eval и exec.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...