使用自定义dict的Eval()在CPython中不起作用[重复]

问题描述 投票:4回答:1

这个问题在这里已有答案:

我正在尝试使用自定义dict作为全局变量运行一些表达式。

class Namespace(dict):
    def __getitem__(self, key):
        if key == "y":
            return 10
        else:
            return super(Namespace, self).__getitem__(key)

def run_with_dict(d):
    print(eval("x + y", d))
    print(eval("[ (p * y) for p in ['foo', 'bar'] ]", d))
    print(eval("{ p: (p * y) for p in ['foo', 'bar'] }", d))

custom = Namespace()
custom["x"] = 2
regular = {"x": 2, "y": 10}

run_with_dict(regular)
run_with_dict(custom)

在CPython 2.7中运行它时,它仅在地图理解上失败:

12
['foofoofoofoofoofoofoofoofoofoo', 'barbarbarbarbarbarbarbarbarbar']
{'foo': 'foofoofoofoofoofoofoofoofoofoo', 'bar': 'barbarbarbarbarbarbarbarbarbar'}
12
['foofoofoofoofoofoofoofoofoofoo', 'barbarbarbarbarbarbarbarbarbar']
Traceback (most recent call last):
  File "<stdin>", line 22, in <module>
  File "<stdin>", line 15, in run_with_dict
  File "<string>", line 1, in <module>
  File "<string>", line 1, in <dictcomp>
NameError: global name 'y' is not defined

但是当它运行PyPy 2.7时,它运行正常。它在任何Python 3中都可以正常工作。

实施差异可以解释什么?这是CPython 2.7中的错误还是未定义的行为?有什么办法让它在两种实现中都能正常工作吗?

python cpython
1个回答
2
投票

CPython经常采用快捷方式。 CPython 2.7中的字典理解要求dict完全是dict而不是它的子类。它不打扰你调用被覆盖的__getitem__方法;它直接为dict.__getitem__,当然看不到名为y的条目。

我不确定这是否是未定义的行为,但是在python 3中被更改的事实意味着它是一个bug。

© www.soinside.com 2019 - 2024. All rights reserved.