我有以下文件app.py
class Baz():
def __init__(self, num):
self.a = num
print self.a
def foo(num):
obj = Baz(num)
和第二个文件main.py
from app import foo
foo(10)
运行文件python main.py
会得到正确的输出。
现在在第二个文件中,我只是导入函数而不是类,虽然我的函数的成功执行也需要类。
导入函数时,Python会自动导入运行该函数所需的所有其他内容,还是会自动搜索当前目录中的类?
答案 0 :(得分:2)
Python不会自动执行任何这些操作。
从模块导入内容时(在本例中为app
模块),Python首先运行相应文件中的所有代码(app.py
)。您撰写的文件app.py
中的代码有两件事:
Baz
foo
当函数foo
运行时,Python在Baz
所属的模块中查找foo
,并且仅在那里。 (好吧,它还会检查函数foo
中定义的局部变量,但除了obj
之外你没有其他任何变量。)具体来说,它会查找app.Baz
。如果您更改main.py
以执行相同的搜索:
from app import foo
foo(10)
import app # same app that was already imported
print app.Baz
您会看到app.Baz
是您在app.py
中定义的类。
如果您将类Baz
的定义放在另一个文件中,并且如果您不导入该文件,则Python将不会运行它。这表明Python 不自动导入依赖项。特别是假设app.py
包含
def foo(num):
obj = Baz(num)
和baz.py
包含
class Baz():
def __init__(self, num):
self.a = num
print self.a
和main.py
保持不变。您将收到错误,因为Python没有运行代码来定义类Baz
。
答案 1 :(得分:2)
正如@DavidZ已经提到的那样,整个Python文件在导入时会被编译。但是当解析函数体时会发生另一件特殊的事情,一个函数知道它应该在局部范围内寻找哪些变量,以及它应该在全局范围内寻找哪些变量(也有自由变量)。
>>> import dis
>>> dis.dis(foo)
7 0 LOAD_GLOBAL 0 (Baz)
3 LOAD_FAST 0 (num)
6 CALL_FUNCTION 1
9 STORE_FAST 1 (obj)
12 LOAD_CONST 0 (None)
15 RETURN_VALUE
因此,必须从全局范围获取Baz
。
但是当我们在另一个中导入app.py时,如何识别这个全局范围 文件?
好吧,每个函数都附加一个特殊的属性__globals__
,它包含它的实际全局命名空间。因此,这是Baz
:
>>> foo.__globals__['Baz']
<class __main__.Baz at 0x10f6e1c80>
因此,app的模块字典和foo.__globals__
指向同一个对象:
>>>sys.modules['app'].__dict__ is foo.__globals__
True
因此,即使您在导入Baz
后在main.py
中定义了另一个名为foo
的变量,它仍会访问实际的Baz
。
__globals__ func_globals
:
对包含函数全局的字典的引用 变量 - 函数所在的模块的全局命名空间 已定义。