本文介绍了Python模块初始化顺序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是来自C ++背景的Python新手.虽然我知道用我以前的C ++知识来尝试找到匹配的概念并不是Pythonic,但我认为这个问题仍然是一个普遍的问题:

I am a Python newbie coming from a C++ background. While I know it's not Pythonic to try to find a matching concept using my old C++ knowledge, I think this question is still a general question to ask:

在C ++中,存在一个众所周知的问题,称为全局/静态变量初始化顺序惨败,原因是C ++无法确定哪个全局/静态变量将首先在编译单元中初始化,因此,全局/静态变量取决于另一个在不同的编译单元中,它们可能比其依赖项对应的对象早初始化,并且当依赖项开始使用依赖项对象提供的服务时,我们将具有未定义的行为.在这里,我不想深入探讨C ++如何解决此问题. :)

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, thus a global/static variable depending on another one in different compilation units might be initialized earlier than its dependency counterparts, and when dependant started to use the services provided by the dependency object, we would have undefined behavior. Here I don't want to go too deep on how C++ solves this problem. :)

在Python世界中,我确实看到了全局变量的使用,即使在不同的.py文件中也是如此,而且我看到的一个典型用法是:在一个.py文件中初始化一个全局对象,在其他.py文件中初始化代码只是毫不费力地开始使用全局对象,假设它必须已经在其他地方初始化了,由于我上面指定的问题,在C ++下,我绝对不接受该对象.

On the Python world, I do see uses of global variables, even across different .py files, and one typycal usage case I saw was: initialize one global object in one .py file, and on other .py files, the code just fearlessly start using the global object, assuming that it must have been initialized somewhere else, which under C++ is definitely unaccept by myself, due to the problem I specified above.

我不确定上述用例是否在Python(Pythonic)中是常见的做法,并且Python一般如何解决这种全局变量初始化顺序问题?

I am not sure if the above use case is common practice in Python (Pythonic), and how does Python solve this kind of global variable initialization order problem in general?

非常感谢!

推荐答案

我认为该声明突出了Python和C ++之间的关键区别:在Python中,没有诸如不同的编译单元之类的东西.我的意思是,在C ++(如您所知)中,两个不同的源文件可能会完全彼此独立地进行编译,因此,如果您比较文件A中的一行和文件B中的一行,就没什么好说的了您将在程序中排在第一位.这有点像具有多个线程的情况:您无法说出线程1中的特定语句是在线程2中的特定语句之前还是之后执行.您可以说C ++程序是并行编译的.

I think that statement highlights a key difference between Python and C++: in Python, there is no such thing as different compilation units. What I mean by that is, in C++ (as you know), two different source files might be compiled completely independently from each other, and thus if you compare a line in file A and a line in file B, there is nothing to tell you which will get placed first in the program. It's kind of like the situation with multiple threads: you cannot say whether a particular statement in thread 1 will be executed before or after a particular statement in thread 2. You could say C++ programs are compiled in parallel.

相反,在Python中,执行从一个文件的顶部开始,并按照文件中的每个语句以明确定义的顺序进行,并在导入它们的位置分支到其他文件.实际上,您几乎可以将import指令视为#include,从而可以确定程序中所有源文件中所有代码行的执行顺序. (好吧,这要复杂得多,因为一个模块只有在第一次导入时才真正执行,并且由于其他原因.)如果并行编译C ++程序,则将按顺序解释Python程序.

In contrast, in Python, execution begins at the top of one file and proceeds in a well-defined order through each statement in the file, branching out to other files at the points where they are imported. In fact, you could almost think of the import directive as an #include, and in that way you could identify the order of execution of all the lines of code in all the source files in the program. (Well, it's a little more complicated than that, since a module only really gets executed the first time it's imported, and for other reasons.) If C++ programs are compiled in parallel, Python programs are interpreted serially.

您的问题还涉及Python中模块的更深层含义. Python模块-包含在单个.py文件中的所有内容-是实际对象.单个源文件中在全局"范围内声明的所有内容实际上都是该模块对象的属性. Python中没有真正的全局范围. (Python程序员经常说全局",实际上在语言中有一个global关键字,但它实际上始终是指当前模块的顶层.)我可以看到,要获得这个概念有点奇怪曾经来自C ++背景.从Java那里花了一些时间来适应我的需要,在这方面,Java与Python相比,与C ++更加相似. (Java中也没有全局范围)

Your question also touches on the deeper meaning of modules in Python. A Python module - which is everything that is in a single .py file - is an actual object. Everything declared at "global" scope in a single source file is actually an attribute of that module object. There is no true global scope in Python. (Python programmers often say "global" and in fact there is a global keyword in the language, but it always really refers to the top level of the current module.) I could see that being a bit of a strange concept to get used to coming from a C++ background. It took some getting used to for me, coming from Java, and in this respect Java is a lot more similar to Python than C++ is. (There is also no global scope in Java)

我将提到在Python中使用变量是完全正常的,而不知道是否已初始化/定义变量.好吧,也许不正常,但至少在适当情况下是可以接受的.在Python中,尝试使用未定义的变量会引发NameError;您不会像在C或C ++中那样会表现出任意行为,因此您可以轻松地处理这种情况.您可能会看到这种模式:

I will mention that in Python it is perfectly normal to use a variable without having any idea whether it has been initialized/defined or not. Well, maybe not normal, but at least acceptable under appropriate circumstances. In Python, trying to use an undefined variable raises a NameError; you don't get arbitrary behavior as you might in C or C++, so you can easily handle the situation. You may see this pattern:

try:
    duck.quack()
except NameError:
    pass

,如果duck不存在,则不执行任何操作.其实,您通常会看到的是

which does nothing if duck does not exist. Actually, what you'll more commonly see is

try:
    duck.quack()
except AttributeError:
    pass

如果duck没有名为quack的方法,则不执行任何操作. (AttributeError是您尝试访问对象的属性时遇到的错误,但是该对象没有该名称的任何属性.)这是通过Python中的类型检查所通过的:我们认为,如果我们需要鸭子做的只是嘎嘎,我们可以要求它嘎嘎叫,如果确实如此,我们不在乎它是否真的是鸭子. (这叫鸭子打字;-)

which does nothing if duck does not have a method named quack. (AttributeError is the kind of error you get when you try to access an attribute of an object, but the object does not have any attribute by that name.) This is what passes for a type check in Python: we figure that if all we need the duck to do is quack, we can just ask it to quack, and if it does, we don't care whether it's really a duck or not. (It's called duck typing ;-)

这篇关于Python模块初始化顺序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 08:10