Python 对象不能全局创建,但可以在本地创建

Python 对象不能全局创建,但可以在本地创建,python,class,module,global,local,Python,Class,Module,Global,Local,我在同一个模块中定义了两个类,并希望在第一个模块中使用第二个类(作为全局变量): 全局_c2收到错误,但本地_c2没有。这是有意义的,因为当编译器浏览这个文件时,它不会知道Class2将要存在。另外,如果我切换类,以便首先定义Class2,它就会工作 然而,我想知道是否有另一种方法来解决这个问题。也许我可以告诉python类2将要存在,所以不用担心,或者我只需要将它们按正确的顺序排列就可以了?您可以执行以下操作(即,在声明类2后回填类1的内容) class Class1(object):

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

全局_c2收到错误,但本地_c2没有。这是有意义的,因为当编译器浏览这个文件时,它不会知道Class2将要存在。另外,如果我切换类,以便首先定义Class2,它就会工作

然而,我想知道是否有另一种方法来解决这个问题。也许我可以告诉python类2将要存在,所以不用担心,或者我只需要将它们按正确的顺序排列就可以了?

您可以执行以下操作(即,在声明类2后回填类1的内容)

class Class1(object):
    pass

class Class2(object):
    pass

Class1.global_c2 = Class2()

在这两种情况下,编译器都会生成完全相同的字节码序列,以便在运行时查找类并实例化它

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


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

@AshwiniChaudhary它正确缩进。
self
参数暗示将
foo
作为一种方法,但它可以以任何方式工作,并且可以很好地说明问题。函数
在哪里>foo()
属于?@AshwiniChaudhary它本身就是一个函数,当然?当我粘贴它时,缩进发生了变化。现在基本上已经修复了,你必须把它们按正确的顺序排列。@delnan这解决了循环依赖性问题-感谢否决票:-/OP描述了问题的解决方案。这里也没有循环依赖性。问题这是一个完全不同的问题,即为什么以及何时这是一个问题。@delnan“但是我想知道是否有其他的方法来解决这个问题。”我已经毫无问题地在Class1之后声明了Class2。这不是一个解决方案吗?我坚持认为你的答案没有任何用处,因为它没有解释任何东西,只是提供了一个脆弱的一次性解决方案。但我将取消我的否决票。谢谢,这是我正在寻找的解释。我希望有一种方法可以在init文件中声明类,但是我想“没有声明”意味着这是不可能的。谢谢,实际上,你不应该接受“没有声明”这个词从字面上讲,你确实不必为这些变量或类型声明变量或类型,但类,甚至函数体是所有效果的声明。此外,Django框架,当人们在构建面向关系的对象模型时遇到这个问题时,选择了这个解决方案:它允许对clas的字符串引用尚未声明(例如(
attr=“Class2”
)而不是
attr=Class2
)。在使用该属性时,如果其类型为string,则会获取对模块上具有该名称的实际类的引用。@jsbueno虽然我一直使用该短语,主要是因为它有一个漂亮的环,但它是完全正确的。
def
class
是常规可执行语句(它们也可以执行多次!),它们创建一个函数/类对象并将其存储在一个名称下。在任何时候,任何东西都不会声明该名称下存在或将存在一个类或函数,甚至不会声明该名称将存在。确实,对于简单的用例,这看起来和感觉上都很像声明(有限制,没有前向声明)但这实际上是一种完全不同的方法。@jsbueno Django示例非常有趣。我想他们保留字符串,并仅在需要访问类时解析它?我的一个序列化框架做了类似的事情,模型类之间的引用存储为
module\u name,class\u name
元组。
class Class1(object):
    pass

class Class2(object):
    pass

Class1.global_c2 = Class2()