Python學習筆記之模塊與包
一、模塊
1、模塊的概念
模塊這一概念很大程度上是為了解決代碼的可重用性而出現的,其實這一概念並沒有多復雜,簡單來說不過是一個後綴為 .py 的 Python 文件而已
例如,我在某個工作中經常需要打印一段很長的內容,很自然地,我會想到將它實現為一個函數,等到需要的時候直接調用即可,而無需重新再輸入這一段內容。現在,假如這樣的工作不僅僅是我一個人在做,比如現在有成千上萬的人需要在他們的工作打印同樣的內容,那麽也很自然地,我會將這份代碼儲存成一個文件發給需要的人。這樣就產生了模塊的概念,我的這一份代碼就可以理解成是一個模塊,它是一份具有一定獨立功能的通用的程序代碼
2、導入模塊
對於導入模塊相信大家都不會陌生,基本的語法是 import module
>>> import random
>>> # 這時可以通過 module.function() 引用其中定義的方法
>>> # 其實,可以把 module 當作是一個新的命名空間
>>> random.randint(0,1)
# 1
另外,還可以直接導入模塊中的方法,基本語法是 from module import function
,此時,該模塊中的其它方法將不可用
>>> from random import randint >>> # 可以直接使用對應的函數名引用函數 >>> randint(0,1) # 0 >>> # 此時,將無法引用模塊中的其它函數 >>> choice([0,1]) # NameError: name ‘choice‘ is not defined
對於上面的語法,一個常見的用法是將某一個模塊中的所有內容導入到當前命名空間中
>>> from random import *
>>> randint(0,1)
# 1
>>> choice([0,1])
# 1
但是,使用上面的方法或許還存在一些問題,就是當引用模塊中的方法名和全局定義的方法名相同時,則會引發命名沖突。此時可以通過引用時重命名解決這個問題,其基本語法如下 import module as alias
或者 from module import function as alias
>>> import random as rd >>> rd.randint(0,1) # 0
註意:無論在程序中使用多少次 import 語句,一個模塊最多只能導入一次
3、搜索路徑
下面,讓我們思考一下更深入的問題?當我們使用 import 語句導入模塊時,編譯器會在哪裏尋找我們需要的模塊呢?一般來說,編譯器尋找模塊的順序如下:
當前目錄
PYTHONPATH 環境變量設置的目錄
由安裝過程決定的默認路徑
我們可以通過 sys 模塊下的 path 變量查看模塊的搜索路徑,另外,我們可以使用 pprint 模塊格式化打印內容
>>> import sys
>>> import pprint
>>> pprint.pprint(sys.path)
# [‘‘,
# ‘C:\\Python\\Python37-32\\Lib\\idlelib‘,
# ‘C:\\Python\\Python37-32\\python37.zip‘,
# ‘C:\\Python\\Python37-32\\DLLs‘,
# ‘C:\\Python\\Python37-32\\lib‘,
# ‘C:\\Python\\Python37-32‘,
# ‘C:\\Users\\user\\AppData\\Roaming\\Python\\Python37\\site-packages‘,
# ‘C:\\Python\\Python37-32\\lib\\site-packages‘]
現在,假如我們自己編寫了一個模塊,我們怎樣可以讓這個模塊應用到其它程序呢?最簡單的一個辦法莫過於將這個文件添加到上面已有路徑中(建議將模塊放在 site-packages 文件夾中,site-packages 是一個專門用來存放第三方模塊的文件夾)
但是這樣的做法並非都是可行的,例如,可能因為權限問題你無法訪問上面的各個目錄,這時候,添加模塊的默認搜索路徑不失為一個可行的辦法,一般來說有三個方法:
- 修改 sys 模塊中 path 變量的值
>>> import sys
>>> sys.append(‘pathName‘)
修改環境變量 PYTHONPATH 的值
在 site-packages 文件夾下添加一個路徑文件,以 .pth 為後綴名,在文件中加入所需目錄名稱
4、隱藏測試代碼
在編寫模塊的時候,我們常常需要對模塊進行局部功能性測試,等待測試成功之後才會將它應用在其它程序中。但是,由於測試所需,總會留下了大量的測試代碼在模塊中,假如不加處理,這些測試代碼將會在引入時對其它程序產生影響,所以,我們需要在程序中隱藏測試代碼
我們首先來看看 Python 中的一個內置變量 __name__
,在主程序中,它的值將被設置為 main
>>> __name__
# ‘__main__‘
所以,在編寫模塊的測試代碼時,我們可以在 if __name__ == ‘__main__‘
程序塊中編寫
if __name__ == ‘__main__‘:
# 測試代碼
這樣,在直接運行模塊時,將會執行測試代碼;但是在引入模塊時,將不會執行測試代碼,如此一來便可以達到我們的目的了
5、模塊查詢
當我們看到一個以前從未接觸過的模塊時,我們可以在哪進行學習和查詢呢?通常有以下幾種途徑
mudule.__doc__
:列出模塊的簡短說明
>>> import math
>>> print(math.__doc__)
# This module is always available. It provides access to the
# mathematical functions defined by the C standard.
dir(module)
:列出方法和屬性
>>> import math
>>> dir(math)
[‘__doc__‘, ‘__loader__‘, ‘__name__‘, ‘__package__‘, ‘__spec__‘, ‘acos‘, ‘acosh‘, ‘asin‘, ‘asinh‘, ‘atan‘, ‘atan2‘, ‘atanh‘, ‘ceil‘, ‘copysign‘, ‘cos‘, ‘cosh‘, ‘degrees‘, ‘e‘, ‘erf‘, ‘erfc‘, ‘exp‘, ‘expm1‘, ‘fabs‘, ‘factorial‘, ‘floor‘, ‘fmod‘, ‘frexp‘, ‘fsum‘, ‘gamma‘, ‘gcd‘, ‘hypot‘, ‘inf‘, ‘isclose‘, ‘isfinite‘, ‘isinf‘, ‘isnan‘, ‘ldexp‘, ‘lgamma‘, ‘log‘, ‘log10‘, ‘log1p‘, ‘log2‘, ‘modf‘, ‘nan‘, ‘pi‘, ‘pow‘, ‘radians‘, ‘remainder‘, ‘sin‘, ‘sinh‘, ‘sqrt‘, ‘tan‘, ‘tanh‘, ‘tau‘, ‘trunc‘]
module.__all__
:列出接口
當使用 from module from *
時,導入的是 __all__
中所含有的內容,若沒有設置 __all__
,則導入 dir(module)
中不以下劃線開頭的所有內容
help(module)
:查看幫助手冊,獲取更多信息module.__file__
:打印源代碼所在的文件路徑,幫助我們閱讀源代碼
>>> import random
>>> random.__file__
# ‘C:\\Python\\Python37-32\\lib\\random.py‘
- https://docs.python.org:一個高效的方法當然是直接查看官方文檔的說明,這個網站上包含了大部分 Python 模塊的說明文檔,可以幫助我們快速掌握特定模塊的用法
二、包
包是為了更好的組織模塊而發展出來的一個概念,它通常是一個目錄,目錄名即包名,目錄中必須有一個 __init__.py
文件,可以用來完成一些初始化的工作,當然也可以為空。然後就是一些模塊文件和子目錄,假如子目錄中也有 __init__.py
文件,則它就是這個包的子包
附:一些常用的 Python 模塊
sys
:訪問與 Python 解釋器緊密相關的變量和函數os
:訪問多個操作系統服務
Python學習筆記之模塊與包