带有自定义dict的Eval()不';我不在CPython工作
我正在尝试使用自定义dict作为全局变量运行一些表达式带有自定义dict的Eval()不';我不在CPython工作,python,cpython,Python,Cpython,我正在尝试使用自定义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)
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
12
['fooofooofooo','barbarbarbar']
{'foo':'fooofoo','bar':'barbarbar'}
12
['fooofooofooo','barbarbarbar']
回溯(最近一次呼叫最后一次):
文件“”,第22行,在
文件“”,第15行,使用命令运行
文件“”,第1行,在
文件“”,第1行,在
NameError:未定义全局名称“y”
但是当它与PyPy2.7一起运行时,它工作得很好。它在任何Python3中都可以正常工作
什么样的实现差异可以解释这一点?这是CPython2.7中的错误还是未定义的行为?我能做些什么使它在两种实现中都能工作吗?CPython经常走捷径。CPython 2.7中的dict理解要求dict完全是一个
dict
,而不是其子类。它不需要调用您被覆盖的\uuu getitem\uu
方法;它直接指向dict.uuu getitem_uuu,当然看不到名为y
的条目
我不确定这是否是未定义的行为,但在python 3中更改的事实意味着这是一个bug。如果有人感兴趣,可以将一个子类dict传递给
FunctionType
构造函数。这不可能是对的,因为前两条语句按预期工作(并且确实调用被重写的\uu getitem\uu
).正如问题中所指出的,只有听写理解失败。@ekhumoro我没有遵循你的逻辑。听写理解和其他测试表达式之间显然有一些细微的差别。为什么不能以这种细微的差别对待听写呢?@ekhumoro第一条语句在模块范围内执行(eval),在Python2中,第二个也在模块scope()中执行。dict comprehension在2和3中创建了一个新的作用域缩短变量查找并直接使用dict.\uuuu getitem\uuuuuuu
。这当然可以在调用\uuu getitem\uuuuuuuu
时进行检查,使子类打印出来。@ekhumaro啊,我想我的答案有点不清楚……我会重新表述一下。我意识到这是玩具演示代码,但有什么原因吗您不能在初始化过程中将y
作为一项添加到dict中?有些变量可能是从磁盘动态加载的,它不知道在给定的评估中会使用哪些变量。