Under C++, there is a well known problem called global/static variable initialization order fiasco, due to C++’s inability to decide which global/static variable would be initialized first across compilation units,
我认为这个声明强调了Python和C之间的关键区别:在Python中,没有不同的编译单元.我的意思是,在C(如你所知)中,两个不同的源文件可能完全独立地编译,因此如果比较文件A中的一行和文件B中的一行,就没有什么可以告诉的你将首先放在程序中.这有点像多线程的情况:你不能说线程1中的特定语句是否在线程2中的特定语句之前或之后执行.你可以说C程序是并行编译的.
相比之下,在Python中,执行从一个文件的顶部开始,并通过文件中的每个语句以明确的顺序继续进行,并在导入点的情况下分支到其他文件.实际上,您几乎可以将import指令视为#include,这样就可以确定程序中所有源文件中所有代码行的执行顺序. (那么它比这更复杂一些,因为一个模块首次被导入时才被真正执行,并且由于其他原因).如果C程序是并行编译的,那么Python程序将被顺序解释.
您的问题也涉及Python中模块的更深层意义.一个Python模块 – 这是一个.py文件中的一切 – 是一个实际的对象.在单个源文件中以“全局”范围声明的内容实际上是该模块对象的属性. Python中没有真正的全局范围. (Python程序员通常会说“全局”,事实上语言中有一个全局关键字,但它总是真正引用当前模块的顶级).我可以看到,有一个奇怪的概念来习惯来自C背景.从Java开始,我已经习惯了一些习惯,在这方面,Java比Python更像Python. (Java中也没有全局范围)
我将提到在Python中使用变量是完全正常的,而不知道它是否被初始化/定义.那么可能不正常,但至少在适当的情况下可以接受.在Python中,尝试使用未定义的变量引发一个NameError;你不会像C或C那样得到任意的行为,所以你可以很容易地处理这种情况.你可能会看到这种模式:
try:
duck.quack()
except NameError:
pass
如果鸭子不存在,它什么都不做.其实,你会更常见的是
try:
duck.quack()
except AttributeError:
pass
如果鸭没有一个名为quack的方法,它什么都不做. (AttributeError是当您尝试访问对象的属性时获得的错误类型,但该对象没有该名称的任何属性.)这是Python中类型检查的传递方式:我们认为,如果我们需要鸭子做的是嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎(这叫鸭子打字;-)