我在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
作为2
与foo['2']['extra_data']['budget'] = 3
的值。
错误是否与某些(无关)密钥在其中有foo['1']['extra_data']['budget'] = 0
的事实有关?
答案 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())