这是我使用Python的第三天,所以原谅新手的错误。所以这是我的工作代码。 person.test()向老板注册回调,老板调用回调,一切正常。
class Boss:
def registerCallback(self,cb):
self.cb = cb
def doCallback(self):
self.cb()
class Person:
def woot(self,data):
print("Woot! ",data)
def test(self,boss,data):
def callback ():
self.woot(data)
boss.registerCallback(callback)
boss = Boss()
person = Person()
person.test(boss,1)
boss.doCallback()
但是,如果我将回调移动到exec()中,则闭包将丢失。回调运行,但 self 和 data 未知,因此对 self.woot(data)的调用失败。
class Boss:
def registerCallback(self,cb):
self.cb = cb
def doCallback(self):
self.cb()
class Person:
def woot(self,data):
print("Woot! ",data)
def test(self,boss,data):
x = "def callback():\n self.woot(data)\nboss.registerCallback(callback)"
exec(x,globals(),locals())
boss = Boss()
person = Person()
person.test(boss,1)
boss.doCallback()
我也尝试编译(),没有运气。有什么想法吗?我真的不想通过老板和后面手动携带自我/数据的副本,因为我的现实代码更复杂。我真的需要一种方法来保持关闭。
答案 0 :(得分:3)
如果你只传递locals
(作为函数的全局数据),那么事情或多或少都有效:
class Person:
def woot(self,data):
print("Woot! ",data)
def test(self,boss,data):
x = "def callback():\n self.woot(data)\nboss.registerCallback(callback)"
exec(x, locals())
当然,如果您还需要全局变量,可以将它们打包在一起:
def test(self, boss, data):
namespace = globals().copy()
local_copy = locals().copy()
namespace.update(local_copy)
x = 'def foo(): pass'
exec(x, namespace)
答案 1 :(得分:2)
为什么您当前的代码会失败?
self
是callback
的免费变量,如果您阅读locals()
的文档,您会发现:
在函数中调用时,
locals()
返回自由变量 阻止,但不在类阻止。
现在来自exec()
的文档:
如果
exec
获得两个单独的对象作为全局和本地,代码将 执行就像它嵌入在类定义中一样。
因此,当我们将两个不同的对象传递给exec()
时,locals()
字典对于callback()
实际上是空的,因为它不能再访问自由变量,因此solution suggested by @mgilson通过合并版locals()
和globals()
应该为您完成。