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

the*_*arl 3 python

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

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

提交one.py

def func():
    print("func() in one.py")

print("top-level in one.py")

if __name__ == "__main__":
    print("one.py is being run directly")
else:
    print("one.py is being imported into another module")
Run Code Online (Sandbox Code Playgroud)

文件two.py

import one

print("top-level in two.py")
one.func()

if __name__ == "__main__":
    print("two.py is being run directly")
else:
    print("two.py is being imported into another module")
Run Code Online (Sandbox Code Playgroud)

当我运行这个:

python two.py
Run Code Online (Sandbox Code Playgroud)

我明白了:

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
Run Code Online (Sandbox Code Playgroud)

如果我只想要执行的func()方法,one.py这就是我选择导入然后调用它的原因,我应该怎么做?为什么它首先被执行?我知道它在导入时因为声明而被调用import one.寻找促使python设计师以这种方式做到的事情!

ick*_*fay 5

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

或许,你可以认为Java在顶层有一个声明性部分,一旦你更深入就会切换到命令式(语句),然后你可能会更进一步表达.但Python并没有真正起作用.Python确实区分了表达式和语句,但它并没有真正具有顶级声明性语法元素.也许你在想这个:

def greet(name):
    print("Hello, {}!".format(name))
Run Code Online (Sandbox Code Playgroud)

...就像在Java中一样,因为它只能出现在某个特定的上下文中.但是没有:在Python中,函数定义是一个语句,就像一个类定义一样,也是一个赋值.

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

我恳请你想一想以下案例.在Python中,如果要创建枚举(没有花哨的新enum模块),您可能会执行以下操作:

FOO, BAR, BAZ = range(3)
Run Code Online (Sandbox Code Playgroud)

对于人眼来说,这可能是我们在导入模块时想要存在的定义.但是,这与你可能期望存在的类似的东西有什么根本的不同__main__

name = input("What's your name? ")
Run Code Online (Sandbox Code Playgroud)

确实没有什么区别,因此Python不会尝试区分它们; 导入模块时,代码将被执行.


额外奖励:Java中的类似行为

想一想:

public class Test {
    static {
        System.out.println("Wait, what? Code is running without being called?");
    }

    public static void main(String[] args) {
        System.out.println("Nothing to see here, move along now...");
    }
}
Run Code Online (Sandbox Code Playgroud)