这个问题在这里已有答案:
我正在尝试使用自定义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中的错误还是未定义的行为?有什么办法让它在两种实现中都能正常工作吗?
CPython经常采用快捷方式。 CPython 2.7中的字典理解要求dict完全是dict
而不是它的子类。它不打扰你调用被覆盖的__getitem__
方法;它直接为dict.__getitem__
,当然看不到名为y
的条目。
我不确定这是否是未定义的行为,但是在python 3中被更改的事实意味着它是一个bug。