【问题标题】:Object cannot be created globally but can locally python对象不能全局创建但可以在本地python
【发布时间】:2012-09-30 14:04:07
【问题描述】:

我在同一个模块中定义了两个类,并想在第一个中使用第二个(作为全局变量):

class Class1(object):
    global_c2 = Class2()

    def foo(self):
        local_c2 = Class2()

class Class2(object):
    pass

global_c2 出现错误,但 local_c2 没有。这是有道理的,因为当编译器查看这个文件时,它不会知道 Class2 将会存在。此外,如果我切换类以便首先定义 Class2 它可以工作。

但是我想知道是否有其他方法可以解决这个问题。也许我可以以某种方式告诉 python Class2 将会存在所以不用担心,还是我只需要将它们按正确的顺序排列?

【问题讨论】:

  • @AshwiniChaudhary 缩进正确。好吧,self 参数暗示 foo 是一种方法,但它可以以任何一种方式工作,并且无论哪种方式都可以很好地说明问题。
  • 函数foo()属于哪里?
  • @AshwiniChaudhary 它本身只是一个函数,对吗?
  • 当我粘贴它时,缩进发生了变化。现已修复
  • 基本上,你必须把它们按正确的顺序排列。

标签: python class module global local


【解决方案1】:

编译器在这里不做任何事情。在这两种情况下,都会生成完全相同的字节码序列来在运行时查找类并实例化它。

不同之处在于语句的运行时间。 Python 模块中的所有代码都是自上而下执行的——没有声明之类的东西,一切都是定义,每个绑定都是动态的。类定义中的代码在遇到类定义时运行(因此第二个类存在并绑定到名称Class2)。函数中的代码在函数被调用时运行,并且由于您在第二个类的定义之前不调用该函数,因此在您调用该函数时它是可用的。

基本上每个解决方案都归结为:延迟绑定,直到您要绑定的对象存在。

【讨论】:

  • 谢谢,这是我正在寻找的解释。我希望可能有一种在 init 文件中声明类的方法,但我认为“没有声明之类的东西”意味着这是不可能的。谢谢
  • 实际上,您不应该从字面上理解“没有声明之类的东西”——确实,您不必为它们声明变量或类型,而是一个类,甚至函数体所有效果的声明。
  • 此外,当人们在构建面向关系的对象模型时遇到这个问题时,Django 框架选择了这个解决方案:它确实允许对尚未成为的类的字符串引用声明(例如(attr = "Class2")而不是attr = Class2)。使用该属性时,如果它的类型是字符串,它会获得对模块上具有该名称的实际类的引用。
  • @jsbueno 虽然我一直使用这个措辞主要是因为它有一个很好的环,但它完全正确。 defclass 是常规的可执行语句(它们也可以执行多次!),它们创建一个函数/类对象并将其存储在一个名称下。在任何时候,任何时候都不会声明存在或将存在该名称下的类或函数,或者甚至该名称将存在。确实,对于简单的用例,这看起来和感觉很像声明(有限制且没有前向声明),但它实际上是一种完全不同的方法。
  • @jsbueno Django 示例非常有趣。我想他们保留字符串并仅在需要访问课程时解决它?我的一个序列化框架做了类似的事情,模型类之间的引用存储为module_name, class_name tuples。
【解决方案2】:

您可以执行以下操作(即在声明 Class2 后回填 Class1 的内容。

class Class1(object):
    pass

class Class2(object):
    pass

Class1.global_c2 = Class2()

【讨论】:

  • @delnan 这解决了循环依赖问题 - 感谢您的反对:-/
  • OP 描述了该问题的解决方案。这里也没有循环依赖。这个问题是一个完全不同的问题,即为什么以及何时这是或不是问题。
  • @delnan “但是我想知道是否有其他方法可以解决这个问题。”我在 Class1 之后声明了 Class2 没有问题。这不是解决方案吗?
  • 我坚持认为您的答案没有用,因为它没有解释任何内容,只是提出了一个脆弱的一次性解决方案。但我会删除我的反对票。
猜你喜欢
  • 2012-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多