Python 模塊初始化的時候,發生了什么?


假設有一個 hello.py 的模塊,當我們從別的模塊調用 hello.py 的時候,會發生什么呢?

方便起見,我們之間在 hello.py 的目錄下使用 ipython 導入了。

hello.py 的代碼如下,分別有模塊變量,函數,類變量,類的靜態方法、類方法和實例方法。

# hello.py

print 'module value'

module_a = 233


def f():
    print 'func name:', f.__name__


class DoClass(object):
    print 'do class'
    c_value = 88

    @classmethod
    def cf(cls):
        print 'cf', cls.cf

    @staticmethod
    def sf():
        print 'sf', DoClass.sf.func_name

    def f(self):
        print self.f

在 hello.py 的目錄下,開啟 ipython,查看結果。

In [1]: import sys

In [2]: sys.modules['hello']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-2-ec73143594c2> in <module>()
----> 1 sys.modules['hello']

KeyError: 'hello'

在還沒有導入 hello 模塊的時候,可以看到,此時系統中是沒有這個模塊的,讓我們進行一次導入。

In [3]: import hello
module value
do class

In [4]: sys.modules['hello']
Out[4]: <module 'hello' from 'hello.pyc'>

導入后,可以看到模塊中的模塊變量和類變量都直接執行了,並且可以看到此時系統中是有了 hello 這個模塊了。此時可以看一下 hello 模塊的屬性:

In [5]: dir(hello)
Out[5]:
['DoClass',
 '__builtins__',
 '__doc__',
 '__file__',
 '__name__',
 '__package__',
 'f',
 'module_a']

可以看到,模塊有模塊變量、函數以及類三個屬性。此時,在 ipython 中再次導入 hello,查看結果:

In [6]: import hello

In [7]:

發現此時什么都沒有輸出,這是因為模塊只有第一次被導入的時候才會被執行。其實,可以把導入模塊作為生成一個新的對象,模塊變量和類變量都是在模塊對象初始化的時候執行的,而函數和類的方法,則不會初始化的時候執行,只有在調用的時候才會執行:

In [7]: hello.f()
func name: f

In [8]: hello.module_a
Out[8]: 233

In [9]: hello.DoClass
Out[9]: hello.DoClass

In [10]: hello.DoClass.c_value
Out[10]: 88

那么,如果在你模塊中導入了其他的模塊,或者導入了其他模塊的方法,又是怎樣的呢?

# hello.py
# -*- coding: utf-8 -*-
import math
from math import sqrt

在模塊中導入 math 以及 math 的 sqrt 方法,然后導入 hello:

In [1]: import hello

In [2]: dir(hello)
Out[2]:
['__builtins__',
 '__doc__',
 '__file__',
 '__name__',
 '__package__',
 'math',
 'sqrt']

In [3]: hello.math
Out[3]: <module 'math' from '/usr/local/Cellar/python/2.7.14_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/math.so'>

In [4]: hello.math.sqrt(100)
Out[4]: 10.0

In [5]: hello.sqrt(1000)
Out[5]: 31.622776601683793

可以看到,導入 hello 后,在 hello 中導入的 math 以及 sqrt 都成了 hello 的方法,這和我們直接在模塊中定義的變量是一致的。

總結:不管在模塊中導入其他的模塊或者直接定義變量,函數以及類,擋在別的模塊中導入該模塊的時候,這些內容都將成為該模塊的屬性。這其實和 Python 中一切皆對象是保持一致的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM