我正在尝试使用自定义字典作为全局变量来运行某些表达式。
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中的错误还是未定义的行为?我有什么办法可以使其在两种实现中都能正常工作?
答案 0 :(得分:2)
CPython通常采用快捷方式。 CPython 2.7中的dict理解期望dict完全是dict
而不是其子类。它不会打扰您覆盖的__getitem__
方法;对于dict.__getitem__
来说是直接的,当然看不到名称为y
的条目。
我不确定这是否是未定义的行为,但是在python 3中进行了更改的事实意味着这是一个错误。