Python中eval嵌套lambda调用self报错:是否为语言Bug?
为什么eval中的lambda引用self会抛出NameError,直接写却正常?
这不是Python的Bug,而是eval的作用域规则和闭包捕获机制的差异导致的,核心原因如下:
- 直接在方法内定义的lambda,是在当前方法的局部作用域中创建的。Python会把方法内的
self作为cell变量处理,闭包(lambda)可以直接捕获这个变量,因此调用lambda时能正常访问self。 - 用eval执行字符串中的lambda时,逻辑完全不同:
- eval默认会使用当前的全局作用域和局部作用域,但函数内的局部作用域在eval中是以字典形式被访问的。
- 字符串中的lambda在定义时,无法将eval字典里的
self转化为可捕获的cell变量。当后续lambda被调用时,它会去全局作用域查找self,自然找不到,于是抛出NameError。
修复示例
你可以通过两种方式解决这个问题:
方式1:显式给lambda绑定self(通过默认参数)
class Foo: def __init__(self): print(eval('self.example(lambda s=self: s.pass_me("example"))')) def example(self, func): return func() def pass_me(self, arg1): print(arg1)
方式2:调用eval时显式传递局部作用域
class Foo: def __init__(self): print(eval('self.example(lambda: self.pass_me("example"))', globals(), locals())) def example(self, func): return func() def pass_me(self, arg1): print(arg1)
原代码对比
原报错代码示例1:
class Foo: def __init__(self): print(eval('self.example(lambda: self.pass_me("example"))')) def example(self, func): return func() def pass_me(self, arg1): print(arg1)
执行时会抛出NameError: name 'self' is not defined。
原正常运行代码示例2:
class Foo: def __init__(self): print(self.example(lambda: self.pass_me("example"))) def example(self, func): return func() def pass_me(self, arg1): print(arg1)
因为lambda直接在__init__的局部作用域创建,能捕获self,所以运行正常。
内容的提问来源于stack exchange,提问作者Code Pal
相关产品推荐
相关产品推荐

