在python中,为什么只有在调用另一个模块的方法时才会执行类体中的代码?

在python中,为什么只有在调用另一个模块的方法时才会执行类体中的代码?,python,Python,与Java不同,在python中,当一个模块被导入到另一个模块中并调用模块的方法时,为什么要执行主体中的代码而不仅仅是方法中的代码 示例(取自另一个SO问题): 文件1.py 文件2.py 当我运行这个时: python two.py 我得到: top-level in one.py one.py is being imported into another module top-level in two.py func() in one.py two.py is being run dire

与Java不同,在python中,当一个模块被导入到另一个模块中并调用模块的方法时,为什么要执行主体中的代码而不仅仅是方法中的代码

示例(取自另一个SO问题):

文件1.py 文件2.py 当我运行这个时:

python two.py
我得到:

top-level in one.py
one.py is being imported into another module
top-level in two.py
func() in one.py
two.py is being run directly
如果我只想执行
one.py
func()
方法,这就是我选择导入然后调用它的原因,我应该怎么做? 为什么一开始就被处决?
我知道它在导入时会被调用,因为语句
importone
。寻找是什么促使python设计师这样做的

之所以执行它,是因为模块中的所有代码(包括函数定义)在第一次导入时都会执行。如果不希望执行代码,请将其放在主节中。

用Python导入模块时,将执行整个文件。这将创建作为模块一部分的所有函数和变量。它不区分只执行函数或类语句

我认为在库中拥有可执行代码的一般模式是:

# one.py
def func():
    print "In file!"

def main():
    # do stuff here
    pass

if __name__=="__main__":
    main()

然后,您可以直接执行文件
python one.py
,或者
导入一个
并从中使用
one.func()

编程语言可以有几种不同的语法元素。例如,大多数语言都有不同的语句和表达式。有些语言,如Java,在顶层有其他语法元素。例如,您不能在顶级或类中编写一些语句,但是如果您想在顶级中放置类定义或类中的方法,那就可以了

您可能会认为Java在顶层有一个声明性的部分,一旦深入,它会切换到命令式(语句),然后可能会在深入时转换为表达式。但是Python并不是这样工作的。Python在表达式和语句之间确实有区别,但它并没有真正的顶级声明性语法元素。也许你在想:

def greet(name):
    print("Hello, {}!".format(name))
…与Java中的方式相同,因为它只能出现在特定的上下文中。但不是:在Python中,函数定义是语句,类定义也是语句,赋值也是语句


由于这种设计,“只导入定义”是不可行的:为了创建定义,必须运行创建定义的代码

我敦促你考虑以下情况。在Python中,如果要创建枚举(不使用新奇的
enum
模块),可以执行以下操作:

FOO, BAR, BAZ = range(3)
在人眼看来,这可能是我们在导入模块时希望存在的定义。但是,这与您可能希望在
\uuuuu main\uuuuu
中存在的类似内容有什么本质上的区别呢

name = input("What's your name? ")
实际上没有区别,所以Python没有试图区分它们;导入模块时,将执行代码


好处:Java中的类似行为 想想这个:

公共类测试{
静止的{
System.out.println(“等等,什么?代码正在运行而没有被调用?”);
}
公共静态void main(字符串[]args){
System.out.println(“这里没什么可看的,现在就走…”);
}
}

Java和Python(在本例中)的关键区别在于Java有一个单独的编译步骤——使用
javac
创建类文件。然而,对于Python,这种编译是在运行时完成的。因此,在导入模块时,Python必须将整个模块源代码编译成字节码。这包括所有那些打印语句以及创建函数和类。你所问的就像是要求
javac
只编译.java文件的一部分。

我完全不明白你为什么会感到困惑。您对执行哪一行代码感到惊讶?您似乎不明白为什么
one.py
使用
if\uuuu name\uuuu==“\uuuu main\uuuu”
语句。
else
子句专门用于只应在导入时执行的代码(即,
\uuuuu name\uuuuuuu
不等于
\uuu main\uuuuuuu
),在运行时编译成字节码的语言,具有许多强制结构和与Java相同的语义。另一方面,您可能还可以编译一种类似Python的语言(可能有一些限制,比如RPython是如何编译的)。虽然这是一个有用的区别,但我不认为这是它真正归结为什么:我认为这不是一个何时编译的问题,而是一个语法有多严格的问题,可以嵌入什么以及这样的语义。@icktoofay我认为你提供了更好的答案(我想你的答案是在我打字一半的时候出现的)。您更好地指出,函数仅在模块代码执行期间创建,而不是在模块编译期间创建。Python中有两个不同但相互交织的步骤。我谈论编译主要是因为OP来自Java背景,其中编译是执行的一个不同步骤。“不可能“只需导入定义”:为了创建定义,必须运行创建定义的代码。“-这清除了它!谢谢。
FOO, BAR, BAZ = range(3)
name = input("What's your name? ")