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

use*_*030 5 python lambda nameerror pdb

我在lambda函数中遇到了一个重新定位的问题.我可以成功输出foo到stdout但是在使用max()包含a 时出现错误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
Run Code Online (Sandbox Code Playgroud)

总而言之,我试图在未知数量的一阶键中max(foo, key=lambda x: foo[x]['extra_data']['budget'])找到嵌套键的最大值budget.

在这种情况下的预期结果可以2作为foo['2']['extra_data']['budget'] = 3vs. 的值foo['1']['extra_data']['budget'] = 0.

该错误是否与某些(不相关的)密钥存在defaultdict于其中的事实有关?

Mar*_*ers 7

您可以设置一个新的地方pdb,但是在这个调试会话使用嵌套的范围是不可见的表达式.嵌套作用域中的任何表达式(例如lambda用于key参数的表达式,使用当前帧的本地名称)都需要是闭包并且会出现此问题.

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

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

max(foo, key=lambda x, foo=foo: foo[x]['extra_data']['budget'])
Run Code Online (Sandbox Code Playgroud)

请参阅obj .__ closure__中究竟包含哪些内容?有关Python编译器如何创建闭包的详细信息.


kyn*_*nan 5

有一个为Python 3错误报告(但是这个问题影响的Python 2.7,以及你发现了),这表明一个解决办法,以替代的Martijn的解决方案:interactpdb其中填充有提示滴你进入一个交互式会话globals() ,并 locals()和你的lambda应按预期工作。


oli*_*der 5

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

globals().update(locals())
Run Code Online (Sandbox Code Playgroud)