每天一小时python官方文档学习(七)————模块与包
6. 模塊
模塊是一個包含Python定義和語句的文件,實際上就是一個正常的.py文件。但是作用和普通需要運行的程序不一樣,它實際上有點像函數。如果說函數實現了代碼的重用,模塊則是實現了函數的重用。我們如果想在不同的程序中使用同一個函數, 不必把這個函數復制到每一個程序中去,而是通過把函數寫在一個模塊中,然后程序通過導入模塊就可以使用這個函數了。
模塊文件名就是模塊名后跟文件后綴 .py 。在一個模塊內部,模塊名(作為一個字符串)可以通過全局變量 __name__ 的值獲得。例如,你可以在當前目錄下創建一個名為 fibo.py 的文件,模塊名即為fibo,而文件中含有以下內容:
# 斐波拉契數列模塊def fib(n): # 打印斐波拉契數列a, b = 0, 1while a < n:print(a, end=' ')a, b = b, a+bprint()def fib2(n): # 返回斐波拉契數列的列表result = []a, b = 0, 1while a < n:result.append(a)a, b = b, a+breturn result這個fibo.py文件就是所謂的模塊文件,它里面就是兩個函數,一個負責打印斐波拉契數列,另一個負責返回斐波拉契數列的列表。我們通過在Python解釋器中輸入import指令即可導入這個模塊:
>>> import fibo在當前的符號表中,這并不會直接進入到定義在 fibo 函數內的名稱;它只是進入到模塊名 fibo 中。你可以用模塊名訪問這些函數:
>>> fibo.fib(1000) 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 >>> fibo.fib2(100) [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] >>> fibo.__name__ #查看全局變量__name__,即顯示模塊名 'fibo'除了直接訪問和調用,把模塊中函數賦值給一個局部變量也是可以的:
>>> fib = fibo.fib >>> fib(500) 0 1 1 2 3 5 8 13 21 34 55 89 144 233 3776.1. 有關模塊的更多信息
我們都知道,模塊可以包含可執行的語句以及函數定義。這些語句通常是用于初始化模塊的,它們僅在模塊第一次在 import 語句中被導入時才執行(實際上,函數定義也是“被執行”的“語句”,模塊級函數定義的執行在模塊的全局符號表中輸入該函數名)。
每個模塊都有它自己的私有符號表,該表用作模塊中定義的所有函數的全局符號表。因此,模塊的作者可以在模塊內使用全局變量,而不必擔心與用戶的全局變量發生意外沖突。
import 語句有一個變體,它可以把名字從(from)一個被調模塊內直接導入(import)到現模塊的符號表里。例如:
>>> from fibo import fib >>> fib(500) 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377這并不會把被調模塊名引入到局部變量表里,因此在這個例子里,fibo 是未被定義的,fibo里面只有fib被導入了,fib2未被導入。如果想導入模塊內定義的所有名稱:
>>> from fibo import * >>> fib(500) 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377這會調入所有不以下劃線_開頭的名稱。 在多數情況下,Python程序員都不會使用這個功能,因為它在解釋器中引入了一組未知的名稱,而它們很可能會覆蓋一些你已經定義過的東西。注意通常情況下從一個模塊或者包內調入 * 的做法是不太被接受的, 因為這通常會導致代碼的可讀性很差。不過,在交互式編譯器中為了節省打字可以這么用。
最后,我們可以在模塊名稱后面加上 as,則跟在 as 之后的名稱將直接綁定到所導入的模塊,這通常用于給模塊名提供一個縮寫,則調用模塊函數時不用寫那么多字,例如import tensorflow as tf、import numpy as np等等。
6.1.1. 以腳本的方式執行模塊
模塊文件既然是.py文件,那當然也可以直接執行它,在Python解釋器中輸入:
>>> python fibo.py # 如果有參數則寫在這里模塊里的代碼會被執行。那直接執行和導入模塊有什么區別呢?
區別就在于 __name__ 的值會不一樣。上面我們看到,導入模塊后,通過fibo.__name__我們能看到__name__的值為’fibo’即模塊名;但是直接執行以后,__name__會被賦值為 "__main__"。 因此,我們可以通過條件判斷語句,規定一些語句時只有直接執行模塊時才有效的:
if __name__ == "__main__":# 直接執行模塊時才會運行的語句,導入模塊時不運行6.1.2. 模塊搜索路徑
當一個模塊被導入時,解釋器會怎么樣在電腦中尋找這個模塊文件呢?
解釋器首先尋找具有該名稱的內置模塊。如果沒有找到,然后解釋器從 sys.path 變量給出的目錄列表里尋找文件。sys.path 初始有這些目錄地址:
- 包含輸入腳本的目錄(或者未指定文件時的當前目錄)
- PYTHONPATH (一個包含目錄名稱的列表,它和shell變量 PATH有一樣的語法)
- 取決于安裝的默認設置
6.1.3. “編譯過的”Python文件
為了加速模塊載入,Python在 __pycache__ 目錄里緩存了每個模塊的編譯后版本,名稱為 module.version.pyc ,其中名稱中的版本字段對編譯文件的格式進行編碼,它一般使用Python版本號。
6.2. 標準模塊
Python附帶了一個標準模塊庫,這些模塊內置于解釋器中,它們提供對不屬于語言核心但仍然內置的操作的訪問,以提高效率或提供對系統調用等操作系統原語的訪問。標準庫也是屬于不要求全部記住,但是常用的應該有印象的知識,建議多查閱官方文檔
這些模塊的集合是一個配置選項,它也取決于底層平臺。例如,winreg 模塊只在Windows操作系統上提供。一個特別值得注意的模塊 sys,它被內嵌到每一個Python解釋器中。變量 sys.ps1 和 sys.ps2 定義用作主要和輔助提示的字符串,這兩個變量只有在編譯器是交互模式下才被定義,例如:
>>> import sys >>> sys.ps1 '>>> ' >>> sys.ps2 '... ' >>> sys.ps1 = 'C> ' C> print('Yuck!') Yuck! C>6.3. dir() 函數
內置函數 dir() 用于查找模塊定義的名稱,它返回一個排序過的字符串列表,這個列表就包括所有類型的名稱:變量,模塊,函數,等等:
>>> import fibo, sys # 先導入fibo和sys模塊 >>> dir(fibo) # 查找fibo模塊 ['__name__', 'fib', 'fib2'] >>> dir(sys) # 查找sys模塊 ['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__','__package__', '__stderr__', '__stdin__', '__stdout__','_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe','_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv','base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder','call_tracing', 'callstats', 'copyright', 'displayhook','dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix','executable', 'exit', 'flags', 'float_info', 'float_repr_style','getcheckinterval', 'getdefaultencoding', 'getdlopenflags','getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit','getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount','gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info','intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path','path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1','setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit','setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout','thread_info', 'version', 'version_info', 'warnoptions']如果沒有參數,dir() 會列出你當前定義的名稱:
>>> a = [1, 2, 3, 4, 5] >>> import fibo >>> fib = fibo.fib >>> dir() ['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']dir() 不會列出內置函數和變量的名稱,如果你想要這些,它們的定義是在標準模塊 builtins 中。
6.4. 包
包是一種通過用“帶點號的模塊名”來構造 Python 模塊命名空間的方法,簡單來說,包就是模塊的集合。例如,模塊名 A.B 表示 A 包中名為 B 的子模塊。正如模塊的使用使得不同模塊的作者不必擔心彼此的全局變量名稱一樣,使用加點的模塊名可以使得 NumPy 或 Pillow 等多模塊軟件包的作者不必擔心彼此的模塊名稱一樣。
假設有這么一個包的文件,它有三個子包,每個子包里面有各自的模塊:
sound/ 包含三個子包的包__init__.py 對sound初始化的模塊formats/ 用于文件格式轉換的子包__init__.py 對formats初始化的模塊wavread.pywavwrite.pyaiffread.pyaiffwrite.pyauread.pyauwrite.py...effects/ 包含不同音效的子包__init__.py 對effects初始化的模塊echo.pysurround.pyreverse.py...filters/ 用于聲音濾波的子包__init__.py 對filters初始化的模塊equalizer.pyvocoder.pykaraoke.py...我們可以從包中導入單個模塊,例如:
import sound.effects.echo這會加載子模塊 sound.effects.echo ,但引用它時必須使用它的全名:
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)也可以直接導入子模塊:
from sound.effects import echo這會加載子模塊 echo ,并使其在沒有包前綴的情況下可用,因此可以不使用全名:
echo.echofilter(input, output, delay=0.7, atten=4)甚至還可以直接導入所需的函數或變量:
from sound.effects.echo import echofilter同樣,這也會加載子模塊 echo,但這會使其函數 echofilter() 直接可用:
echofilter(input, output, delay=0.7, atten=4)總結
以上是生活随笔為你收集整理的每天一小时python官方文档学习(七)————模块与包的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 每天一小时python官方文档学习(六)
- 下一篇: 二叉树N叉数的前中后序遍历总结,pyth