' NameError:未定义全局名称'在pdb下,对于确实存在的字典

时间:2016-02-02 11:05:54

标签: python lambda pdb nameerror

我在lambda函数中遇到了问题重新定位问题。我可以成功输出foo到stdout但是在使用包含max()的{​​{1}}时出错 - 请参阅下面的简化代码...

总而言之,我正在尝试在未知数量的一阶键中找到嵌套键lambda的最大值。

budget

总而言之,我尝试使用(Pdb) foo = self.some_method() # some_method() returns a dict, printed in the next step (Pdb) pp foo {'1': {'count': 1, 'extra_data': {'activity-count': 1, 'budget': 0, [...MORE KEY-VALUE PAIRS HERE...] 'version': 1}, [...LOTS MORE KEY-VALUE PAIRS HERE...] 'elements_total': defaultdict(<type 'int'>, {'result': 1, 'another_key': 2}), 'extra_year_data': defaultdict(<function <lambda> at 0x10e05bd70>, {})}, '2': {'count': 1, 'extra_data': {'activity-count': 1, 'budget': 3, [...MORE KEY-VALUE PAIRS HERE...] 'version': 1}, [...LOTS MORE KEY-VALUE PAIRS HERE...] 'elements_total': defaultdict(<type 'int'>, {'result': 1, 'another_key': 2}), 'extra_year_data': defaultdict(<function <lambda> at 0x10e05bd70>, {})}} (Pdb) max(foo, key=lambda x: foo[x]['extra_data']['budget']) *** NameError: global name 'foo' is not defined 在未知数量的一阶键中找到嵌套键max(foo, key=lambda x: foo[x]['extra_data']['budget'])的最大值。

在这种情况下,预期结果可以是budget作为2foo['2']['extra_data']['budget'] = 3的值。

错误是否与某些(无关)密钥在其中有foo['1']['extra_data']['budget'] = 0的事实有关?

3 个答案:

答案 0 :(得分:7)

使用pdb设置新的本地,但在此调试器会话中使用嵌套作用域的表达式不可见。嵌套作用域中的任何表达式,例如用于lambda参数的key,使用当前帧的本地名称,将需要是一个闭包,并且将有这个问题。

这是调试器和Python编译工作方式的限制;只有在需要生成它们的函数在同一会话中编译时才能创建闭包。由于您正在调试的函数是在没有foo作为闭包的情况下编译的,因此lambda表达式不能使用它。

您可以将本地绑定到lambda(使其成为本地而不是闭包):

max(foo, key=lambda x, foo=foo: foo[x]['extra_data']['budget'])

有关Python编译器如何创建闭包的详细信息,请参阅What exactly is contained within a obj.__closure__?

答案 1 :(得分:4)

有一个bug report for Python 3(但这个问题会影响Python 2.7以及你发现的),这表明workaround可以替代Martijn的解决方案:interact at pdb提示会将您带入一个交互式会话,该会话中填充了globals() locals(),您的lambda应该按预期工作。

答案 2 :(得分:3)

这会弄乱您的全局范围,但这是我在使用python 2.7的情况下使用的一种快速(肮脏)解决方法:

globals().update(locals())