我有一个dict
子类,如下所示:
class MyDict(dict):
def __getitem__(self, name):
return globals()[name]
>>> 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
但不适用于函数对象?
答案 0 :(得分:1)
不是一个完整的答案,但似乎正在发生的事情是CPython在访问内置函数时忽略了自定义__getitem__
。它似乎将MyDict
视为正常(非子类)dict。如果dict中实际存在'__builtins__'
键,则一切正常:
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
。