Python import语句是否也自动导入依赖项?

时间:2015-03-31 11:09:45

标签: python function python-import

我有以下文件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会自动导入运行该函数所需的所有其他内容,还是会自动搜索当前目录中的类?

2 个答案:

答案 0 :(得分:2)

Python不会自动执行任何这些操作。

从模块导入内容时(在本例中为app模块),Python首先运行相应文件中的所有代码(app.py)。您撰写的文件app.py中的代码有两件事:

  1. 定义班级Baz
  2. 定义函数foo
  3. 当函数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

来自data-model page

__globals__ func_globals

  

对包含函数全局的字典的引用   变量 - 函数所在的模块的全局命名空间   已定义