如果将自定义字典用作函数的全局变量,为什么不能访问内置函数? [英] Why can't I access builtins if I use a custom dict as a function's globals?
问题描述
我有一个 dict
子类,如下所示:
I have a dict
subclass like this:
class MyDict(dict):
def __getitem__(self, name):
return globals()[name]
This class can be used with eval
and exec
without issues:
>>> eval('bytearray', MyDict())
<class 'bytearray'>
>>> exec('print(bytearray)', MyDict())
<class 'bytearray'>
但是如果我使用 types.FunctionType
构造函数,该函数无法访问任何内置函数:
But if I instantiate a function object with the types.FunctionType
constructor, the function can't access any builtins:
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
用 globals()
或 dict(globals())替换
或事件 MyDict()
{'__ builtins__':__builtins __}
使代码打印< class'bytearray'>
如预期。
Replacing MyDict()
with globals()
or dict(globals())
or event {'__builtins__': __builtins__}
makes the code print <class 'bytearray'>
as expected.
我不知道此异常来自何处。谁能解释这种行为?为什么它可以与 eval
一起使用,但不能与函数对象一起使用?
I don't understand where this exception is coming from. Can anyone explain this behavior? Why does it work with eval
but not with a function object?
推荐答案
不是一个完整的答案,但是似乎正在发生的事情是CPython在访问内置函数时会忽略自定义 __ getitem __
。似乎将 MyDict
当作普通(未分类)的字典对待。如果字典中确实存在'__ builtins __'
键,则说明一切正常:
Not a complete answer, but what seems to be happening is that CPython ignores the custom __getitem__
when it accesses the builtins. It seems to treat MyDict
like a normal (not subclassed) dict. If the '__builtins__'
key is actually present in the dict, then everything works correctly:
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
。
The question remains why this only happens with FunctionType
, and not with eval
and exec
.
这篇关于如果将自定义字典用作函数的全局变量,为什么不能访问内置函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!