天天看點

Python學習筆記(六) 子產品與包

這篇文章将會介紹 Python 中子產品與包的相關内容

1、子產品與包

子產品 (

module

)   這個概念最初是為了代碼封裝和可重用性而出現的,每個字尾為

.py

的檔案都是一個子產品

而包 (

package

) 是為了更好地組織子產品而發展出來的概念,在 Python 3.3 後,每個目錄都被稱為一個包

而在 Python 3.3 之前,隻有目錄中有

__init__.py

才會被識别為一個包

2、導入子產品

我們可以使用

import

語句導入子產品,正常的文法是

import module

, 在首次導入子產品時:

  1. 首先建立一個新的命名空間,并在該命名空間内執行子產品

    module

    中的代碼
  2. 然後在目前命名空間用名稱 

    module

     引用新的命名空間 

是以我們在目前命名空間内才能通過

module.symbol

通路子產品中的變量

>>> import random
>>> random.randint(0, 1)
# 1
           

我們也能使用

from module import symbol

module

中導入指定的

symbol

到目前命名空間

這樣我們就能在目前命名空間直接通路導入的變量,但是要注意此時不能通路子產品中的其他變量

>>> from random import randint
>>> randint(0, 1)
# 1
           

我們還能通過

as

用指定的名稱引用新的命名空間和導入的變量

>>> # 通過 `as` 指定名稱引用新的命名空間
>>> import random as rd
>>> rd.randint(0, 1)
# 1
>>> # 通過 `as` 指定名稱引用導入的變量
>>> from random import randint as ri
>>> ri(0, 1)
# 1
           

3、導入包

我們可以用

import

語句導入包,正常的文法是

import package

,在執行這條語句時:

  1. 首先建立一個新的命名空間,并在該命名空間内執行包内

    __init__.py

    中的代碼
  2. 然後在目前命名空間用名稱

    package

    引用新的命名空間

__init__.py

一般用于指定導出的内容,若該檔案缺失或内容為空,

import package

不會有任何效果

import package

print(package.module.symbol)
           

我們也能用

from package import module

package

中導入指定的

module

到目前命名空間

這樣我們就能在目前命名空間直接通路導入的子產品

module

以及子產品中的變量

from package import module

print(module.symbol)
           

我們還能用

from package.module import symbol

package

中的

module

導入指定的

symbol

這樣我們就能在目前命名空間直接通路導入的變量

symbol

from package.module import symbol

print(symbol)
           

4、搜尋路徑

下面讓我們思考一個更深入的問題?當我們使用

import

語句導入子產品時,解釋器在哪裡找所需的子產品呢?

  1. 緩存路徑(可以通過

    sys.modules

    檢視,儲存着之前導入的所有子產品及其查找路徑)
  2. 内置子產品(可以通過

    sys.builtin_module_names

    檢視)
  3. 其他位置(可以通過

    sys.path

    檢視,包括入口檔案所在目錄、

    PYTHONPATH

    環境變量指定目錄)

如果現在我們需要讓程式引用一個不在上述路徑所指定的目錄中的子產品,可以怎麼處理呢?

一個簡單而有效的辦法就是在程式中修改

sys.path

的值,添加上述子產品所在路徑即可

5、隐藏測試代碼

在編寫子產品時,我們常常需要對子產品進行單元測試,等待測試成功後才會将其應用到其它程式上

由于測試所需,在子產品中可能會留下大量測試代碼,這些測試代碼在子產品被引用時可能會影響到正常運作

是以,我們有必要在子產品中隐藏測試代碼,具體的方法如下:

在 Python 中有一個内置變量

__name__

,隻有當一個檔案作為入口檔案時,它的值才為

__main__

是以我們可以将測試代碼寫在以下條件語句塊内,這樣的話隻有在直接運作子產品時才會執行這些代碼

if __name__ == '__main__':
    # 測試代碼
           

6、子產品查詢

最後一個問題,當我們看到一個從未接觸過的子產品時,可以在哪裡進行學習呢?通常有以下幾種途徑:

  • mudule.__doc__

    :列出子產品的簡短說明
>>> import random
>>> print(random.__doc__)
# Random variable generators.
# 
#     integers
#     --------
#            uniform within range
# 
#     sequences
#     ---------
#            pick random element
#            pick random sample
#            pick weighted random sample
#            generate random permutation
# 
#     distributions on the real line:
#     ------------------------------
#            uniform
#            triangular
#            normal (Gaussian)
#            lognormal
#            negative exponential
#            gamma
#            beta
#            pareto
#            Weibull
# 
#     distributions on the circle (angles 0 to 2pi)
#     ---------------------------------------------
#            circular uniform
#            von Mises
# 
# General notes on the underlying Mersenne Twister core generator:
# 
# * The period is 2**19937-1.
# * It is one of the most extensively tested generators in existence.
# * The random() method is implemented in C, executes in a single Python step,
#   and is, therefore, threadsafe.
           
  • module.__all__

    :列出子產品的可用接口
>>> import random
>>> print(random.__all__)
# ['Random', 'seed', 'random', 'uniform', 'randint', 'choice', 'sample', 'randrange', 'shuffle', 'normalvariate', 'lognormvariate', 'expovariate', 'vonmisesvariate', 'gammavariate', 'triangular', 'gauss', 'betavariate', 'paretovariate', 'weibullvariate', 'getstate', 'setstate', 'getrandbits', 'choices', 'SystemRandom']
           
  • module.__file__

    :列印子產品源代碼的所在路徑
>>> import random
>>> print(random.__file__)
# C:\Python\Python37-32\lib\random.py
           
  • help(module)

    :檢視幫助手冊,擷取更多資訊
  • 最後一個方法當然是直接看官方文檔的說明啦:https://docs.python.org