Python核心編程筆記(第12章 模塊)

採用書籍Python核心編程(第二版),人民郵電出版社,2008年7月第1版。本書以Python2.5爲主,但筆記主要以Python3.6爲主。

第12章

模塊是用來組織Python代碼的方法,而包是用來組織模塊的

12.1 模塊和文件

  1. 代碼量變大—>把代碼分成有組織的代碼段,彼此能夠交互—>代碼可以共享,實現重用。那些自我包含並且有組織的代碼片段就是模塊(module),吧其他模塊加入到你的模塊中的操作叫做導入(import)
  2. 如果說模塊(module)是按照邏輯來組織Python代碼的方法,那麼文件便是物理層上組織模塊的方法。一個文件被看作一個獨立模塊,一個模塊也可以被看作是一個文件
  3. 模塊命名空間(也叫名稱空間,namespace):從名稱到對象的關係映射集合,模塊的屬性名稱均屬於該集合。每個模塊都定義了自己的唯一的名稱空間。
  4. 搜索路徑和路徑搜索:前者爲名詞,後者爲動詞。前者是一組預定義有用途的目錄,後者是查找某個文件的操作。默認搜索路徑是在安裝時指定的,可以用環境變量PYTHOINPATH或保存在sys模塊中的sys.path變量進行修改。

12.2 名稱空間

  1. 名稱空間是名稱(標識符)到對象的映射。向名稱中添加名稱的操作過程涉及綁定標識符到指定對象的操作(以及給對象的引用計數加1)。
  2. 在程序執行期間,有2個或3個活動的名稱空間:局部名稱空間、全局名稱空間和內建名稱空間。局部名稱空間會變化,可能有可能無,所以是“2個或3個”。
  3. Python解釋器會首先加載內建名稱空間。隨後加載全局名稱空間,它會在模塊開始執行後變爲活動名稱空間。如果在執行期間調用了一個函數,那麼將會創建除第三個名稱空間,即局部名稱空間。(Java中一對新的大括號會生成一個局部作用域,Python和其不同)
  4. 名稱空間和變量作用域:名稱空間是純粹意義上的名字和對象件的映射關係,而作用域還指出了在代碼中可以訪問這些名字的物理位置。
  5. 名字查找:訪問一個屬性時,按局部名稱空間—>全局名稱空間—>內建名稱空間的順序查找它的名字。若沒有找到,就會出現NameError;若局部和全局或內建有相同的名稱,訪問時會覆蓋。
  6. Python中一切皆對象。你可以在任何需要放置數據的地方獲得一個名稱空間。

12.3 導入模塊

  1. 導入語句:import module。
  2. 模塊在頂層導入,它的作用域就是全局的;在函數中導入,它的作用域是局部的。
  3. 如果模塊被第一次導入,它將被加載並執行。模塊的頂層代碼將直接被執行,包括全局變量和函數的聲明(函數本身並不會被執行,因爲沒有調用啊哈哈哈)。
  4. 一個模塊可被導入多次。,但只被加載和執行一次(就是第一次),這樣阻止了多重導入時代碼被多次執行。若用戶自定義模塊被修改需重新導入,需使用reload。
  5. from-import語句:把模塊中的屬性導入到當前的名稱空間,方便進行訪問;不可以修改該屬性,因爲修改相當於定義了一個新的同名的局部變量!
# 導入模塊推薦順序
import Python標準庫模塊
import Python第三方模塊
import 應用程序自定義模塊
# 導入模塊中的指定屬性 from-import
from module import name1, name2, ...
from module import * # 導入所有屬性,不推薦
# 擴展import語句的as,取別名,方便理解和記憶
import module as XXX
from module import name1 as XXX
import numpy as np
import pandas as pd
# 重新導入自定義模塊需要使用imp模塊中的reload方法
from imp import reload
reload(module)

12.4 模塊內建函數

系統爲模塊提供了一些功能上的支持。

# 1.__import__():實際上導入模塊的函數
var = __import__(module_name) # 參數爲字符串;返回值爲對應的模塊對象,所以需要將引用傳給變量,否則無法使用該模塊
sys = __import__('sys') # 等價於import sys 

# 2.globals()和locals():返回調用者全局和局部名稱空間的字典的函數
# 在全局名稱下,globals()和locals()返回相同的字典,因爲此時的局部名稱空間就是全局空間
def foo():
    print('calling foo()...')
    num = 123
    name = 'foo'
    print("foo()'s globals:", globals().keys())
    print("foo()'s locals:", locals().keys())
print("__main__()'s globals:", globals().keys())
print("__main__()'s locals:", locals().keys())
foo()

# 3.reload():重新導入模塊需要使用imp模塊中的reload方法
# 模塊必須是全部導入(不是from-import),reload()函數的參數必須是模塊自身而不是模塊名字的字符串,reload()函數重新導入導致模塊會執行
from imp import reload
reload(module)

12.5 包

包是一個有層次的文件目錄結構,它定義了一個由模塊和子包組成的Python應用程序執行環境。Python1.5加入了包,用來幫助解決如下問題:

  • 爲平坦的名稱空間加入有層次的組織結構
  • 允許程序員把有聯繫的模塊組合到一起
  • 允許分發這使用目錄結構而不是一大堆混亂的文件
  • 幫助解決有衝突的模塊名稱
# 1.目錄結構
# 導入包中的模塊:from package.module import sub_module
# 模塊下的__init__.py 文件,用於初始化模塊。

# 2.使用from-import導入包:
# from package import * # 導入package.module下的所有模塊(__all__變量中定義的)
# __init__.py 中的 __all__ 變量包含執行該語句時應該導入的模塊名字符串列表。

# 3.絕對導入
# 所有的導入都被認爲是絕對的,即這些被導入的模塊必須通過Python路徑(sys.path或是PYTHONPATH)來訪問。

# 4.相對導入
from Phone.Mobile.Analog import dial # 絕對導入
from .Analog import dial # 相對導入
from ..Fax import G3.dial # 相對導入

12.6 模塊的其他特性

  1. Python解釋器在標準模式下啓動時,一些模塊會被解釋器自動導入,用於系統相關操作。sys.modules變量包含一個由當前載入(完整且成功導入)到解釋器的模塊組成字典,模塊名爲鍵,對應的位置爲值。
  2. 阻止屬性導入。如果不想讓某個模塊屬性被 from module import * 導入 ,可以在不想導入的屬性名稱加上一個下劃線_。
  3. 不區分大小的導入。指定 PYTHONCASEOK 環境變量,以不區分大小寫地導入模塊。

12.7 相關模塊

  • imp:這個模塊提供了一些底層的導入者功能。
  • modulefinder:該模塊允許你查找 Python 腳本所使用的所有模塊。
  • pkgutil:該模塊提供了多種把 Python 包打包爲一個”包”文件(*.pkg)分發的方法。
  • site:和 *.pth文件配合使用, 指定包加入 Python 路徑的順序。
  • zipimport :使用該模塊導入 ZIP 歸檔文件中的模塊。
  • distutils:該模塊提供了對建立、 安裝、分發 Python 模塊和包的支持。

參考資料:

  1. 《Python核心編程》學習筆記
發佈了79 篇原創文章 · 獲贊 92 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章