在exec()中定义的回调期间关闭丢失

2024-03-29 09:02:00 发布

您现在位置:Python中文网/ 问答频道 /正文

今天是我使用Python的第三天,所以请原谅新手的错误。这是我的工作代码。你知道吗个人测试()向老板注册回调,老板调用回调,一切正常。你知道吗

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()中,则闭包将丢失。回调运行,但是selfdata未知,因此调用自拍(数据)失败。你知道吗

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()

我也试过编译(),没有运气。有什么想法吗?我真的不想手动将self/数据的副本通过boss传递回来,因为我的实际代码要复杂得多。我真的需要一个方法来保持关闭。你知道吗


Tags: 代码testselfdatadefcallbackclassperson
2条回答

为什么当前代码失败?

selfcallback的自由变量,如果您阅读^{}的文档,您将发现:

Free variables are returned by locals() when it is called in function blocks, but not in class blocks.

现在从^{}的文档来看:

If exec gets two separate objects as globals and locals, the code will be executed as if it were embedded in a class definition.

因此,当我们将两个不同的对象传递给exec()时,locals()字典对于callback()实际上是空的,因为它不能再访问自由变量,因此传递locals()globals()的合并版本的solution suggested by @mgilson应该为您做这件事。你知道吗

如果只传递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())

当然,如果您也需要globals,您可以将它们打包在一起:

def test(self, boss, data):
  namespace = globals().copy()
  local_copy = locals().copy()
  namespace.update(local_copy)
  x = 'def foo(): pass'
  exec(x, namespace)

相关问题 更多 >