如果将自定义字典用作函数的全局变量,为什么不能访问内置函数? [英] Why can't I access builtins if I use a custom dict as a function's globals?

查看:102
本文介绍了如果将自定义字典用作函数的全局变量,为什么不能访问内置函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 dict 子类,如下所示:

I have a dict subclass like this:

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

此类可与 eval一起使用 exec 没有问题:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆