python 歷險記(五)—— python 中的模塊

来源:https://www.cnblogs.com/reycg-blog/archive/2018/11/19/9976078.html
-Advertisement-
Play Games

這次我們繼續探險,來搞定 python 中的模塊(module)。**兵馬未動,糧草先行**,開工之前先看看基礎是否補齊了。 ...


目錄

前言

這次我們繼續探險,來搞定 python 中的模塊(module)。兵馬未動,糧草先行,開工之前先看看基礎是否補齊了^_^。

基礎

模塊的概念你一定不會陌生吧,這是一個非常寬泛的概念,在各行各業都會用到。這裡我們涉及的只是軟體中的模塊概念。說到模塊,就得先瞭解下模塊化程式設計的概念。(如果您對模塊化程式設計的概念已經爛熟於心,盡可以略過,而直接跳到下一節)

模塊化程式設計

模塊化程式設計是指進行程式設計時將一個大程式按照功能劃分為若幹小程式模塊,每個小程式模塊完成一個確定的功能,並且在這些模塊之間建立必要的聯繫,通過模塊的相互協作完成整個功能的程式設計方法。

——百度百科

舉個例子,假如我們要造一輛汽車,就可以先將汽車分成四個部件:發動機、底盤、電氣設備、車身。每個部件都是一個模塊,都會完成自己專屬的功能,同時也預留了和其他部件配合的介面。當這幾部分建造完成時,就可以組合在一起,從而完成了整個汽車的建造。

類比一下,汽車就是整個程式,而像發動機,底盤等就是程式中各個小的模塊。只有當各個模塊正常工作,並且暴露的介面和其他模塊的介面完全契合,才能組合成一個完整且正常工作的程式。

模塊化有哪些好處?

當然,如果不將程式分解成一個個獨立的部分,而是整個一大坨,也能夠完成所要的功能。那麼為什麼教科書還有實際使用中都會提倡模塊化程式設計?這樣做有什麼好處呢?

  1. 控製程序設計的複雜度

    不知你看過《代碼大全》沒有,裡面有一句非常著名的格言:軟體的首要使命就是管理複雜度。完整的軟體功能複雜度是非常高的,如果不使用有效的方法加以管理,很可能會陷入複雜的泥潭中不可自拔。而將程式分解成模塊,則會將整體功能的複雜度有效的下分到各個模塊中。每個模塊只要能夠管理好自己的複雜度就可以了。

  2. 提高代碼的重用性

    還是以造汽車為例,假設我造了一個很牛的發動機,多款車型都可以使用它。程式設計也一樣,如果一個模塊能夠完成特定的功能,且與父程式耦合度較小,多個程式都可以使用它。

  3. 易於維護和擴展

    小 A 寫了一個程式,並將各個部分劃分的非常明確,再加以人性化的函數命名和註釋。即使有一天小 A 離職了,小 B 要接過來維護以及在此基礎上再開發新的功能也不難。

既然模塊化就這麼多好處, 強大的 python 當然也會吸收這個優秀的設計思想,並且在語言中有所體現,那就是 python 的模塊(module)。

什麼是 python 中的模塊?

先來看一個示例:

  1. 創建 python 文件 a.py,併在文件中定義函數 sum

    def sum(a, b):
        return a + b
  2. 創建 python 文件 b.py, 並調用 sum 函數

    from a import sum
    
    print(sum(1, 2)) # 3

文件 a.py 就是一個模塊(module),b.py就是一個主模塊(main module)。

b.py 中有這麼一句 from a import sum ,是指將模塊 a 中的 sum 函數導入到當前模塊中。我們定義的文件名是 a.py ,而模塊名就是去掉尾碼後得到的 模塊 a。那麼能不能再多導入幾個函數或者導入模塊 a 的全部函數呢?當然可以,這個我們後面講。

調用模塊時,通過文件名就可以確定模塊的名字,那麼在模塊(module)內部,能知道自己姓甚名誰嗎?還真能。

每個模塊都有一個全局變數 __name__ ,它就是模塊的名字。上面 a.py 的內容不變,修改下 b.py 的內容。

import a

print(a.__name__)  # a
print(a.sum(1, 2))  # 3

來,一起總結下:

  1. python 模塊(module) 是指包含 python 定義(包括 類,函數,變數)和語句的文件(.py做尾碼)
  2. 模塊名就是模塊文件名稱去掉.py 尾碼
  3. 在模塊內部,可以通過全局變數 __name__ 得到模塊名稱

引入模塊有幾種方式?

要導入模塊並調用,前提要導入的 python 模塊中有料(函數,變數,class)才可以。先來定義一個 python 模塊 calc

def plus(a, b):
    return a + b


def subtract(a, b):
    return a - b

再創建一個 main.py 文件,在其中做引入操作。okay,準備好了,那我們來逐個看下可以引入模塊的方式吧。

  • 引入整個模塊,調用時需要加上模塊名

    import calc
    
    print(calc.plus(1, 2)) # 3
    
    print(calc.subtract(2, 1)) # 1
  • 引入模塊特定的函數或變數,調用時無需加模塊名

    from calc import plus, subtract
    
    print(plus(1, 2))  # 3
    
    print(subtract(2, 1))  # 1
  • 引入整個模塊,調用時無需加上模塊名

    from calc import *
    
    print(plus(1, 2))  # 3
    
    print(subtract(2, 1))  # 1
  • 引入整個模塊,並對模塊重命名,調用時加上重命名後的模塊名

    import calc as calculator
    
    print(calculator.plus(1, 2))  # 3
    
    print(calculator.subtract(2, 1))  # 1
  • 引入模塊特定的函數或變數,並對其重命名,調用時無需加模塊名

    from calc import plus as add, subtract as sub
    
    print(add(1, 2))  # 3
    
    print(sub(2, 1))  # 1

    數一下,一共是 6 種方式,歸納一下就是 from , import , as , * 這些符號的組合而已。

模塊的查找順序

在上幾篇文章中已經用瞭如 osshutilsjson 等多個模塊 ,這些模塊都是 python 的內置模塊。相比之下,我們剛纔使用的 calc 模塊就是自定義模塊。

假設我們使用 import calc 導入 calc 模塊, python 在啟動時按照什麼樣的順序來查找這個模塊呢?

  1. 先查找內置(built-in)模塊中有沒有,如果沒有轉到 2
  2. 查找 sys.path 變數指定的路徑下有沒有, 有的話就使用,沒有就報錯

sys.path 變數中存儲了那些路徑呢?

  1. 當前運行的 python 腳本所在的目錄

  2. 環境變數 PYTHONPATH 中的路徑,它和 shell 環境變數 PATH 差不多

    這個變數可以使用 python 腳本在運行時修改它

  3. 預設的 python 安裝包的路徑

想要看下你的電腦當前 sys.path 有哪些路徑嗎?運行下麵代碼就可以

import sys
print(sys.path)

查找模塊的順序是從前向後,只要查到就使用,因此這個變數存儲路徑的順序很重要。

模塊中包含執行語句的情況

如果引入的模塊中包含一些執行語句,那麼在導入模塊時這些語句就會執行。但是即使同樣的模塊被導入了兩次,這些語句也只能執行一次。

來看下麵的例子, 定義 calc 模塊

print('I am clac module')


def plus(a, b):
    return a + b


def subtract(a, b):
    return a - b

並且在 main.py 中定義導入兩次 calc 模塊的函數

from calc import plus
from calc import subtract


print(plus(1, 2))
print(subtract(1, 2))

結果是 'I am clac module' 只會被列印一次。

用 dir() 函數來窺探模塊

dir() 函數是 python 的內置函數,可用來獲取模塊的屬性,方法等信息,當我們剛接觸一個模塊,不清楚它由哪些有用的屬性和方法時,就可以用 dir() 來一探究竟。

以常用的 json模塊 為例,我們來展示下它的屬性和方法

import json

print(dir(json))
# ['JSONDecodeError', 'JSONDecoder', 'JSONEncoder', '__all__', '__author__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', '_default_decoder', '_default_encoder', 'codecs', 'decoder', 'detect_encoding', 'dump', 'dumps', 'encoder', 'load', 'loads', 'scanner']

其中以雙下劃線開頭的變數,如 __name__ 並非是模塊自己定義的,而是與模塊相關的預設屬性。

如果我想查看當前模塊內的所有屬性和方法呢?去掉 dir() 函數的參數就可以。拿上節的代碼為例來看下。

from calc import plus
from calc import subtract


print(plus(1, 2))
print(subtract(1, 2))
print(dir())
# ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'plus', 'subtract']

我們會看到 calc 模塊的 plussubstract 方法也展示了出來,那麼 dir 函數究竟是從哪裡獲取的數據,背後的機理是什麼呢?

其實每個模塊內部都有一個子集的私有符號表,它就是模塊內所有函數和方法共用的全局符號表。當模塊 B 導入模塊 A 時,就會把要導入的模塊 A 或者特定的方法,屬性放置到模塊 B 的全局符號表中,dir() 函數也就是從模塊中的全局符號表中獲取出的值。

python 的內置模塊有哪些?

python 的內置模塊太豐富了,幾乎可以滿足我們日常的任何需求。既然有輪子就在那裡,而且這輪子又快又好,又何必再造輪子呢?快來看下它的常用內置模塊有哪些。

模塊名 功能簡述
calendar 與日期相關
datetime 處理日期和時間
csv 讀寫 csv 文件
json 讀寫 json 格式數據
collections 提供有用的數據結構
io 處理 I/O 流
os 基本的操作系統函數訪問
shutil 高級文件處理
tempfile 創建臨時文件和目錄
logging 日誌功能
random 生成偽隨機數
copy 複製數據相關
codec 編解碼
re 正則表達式
uuid 全局唯一標識符 (UUID)
multiprocessing 運行多個子進程
threading 線程
concurrent 非同步
argparse 解析命令行參數
atexit 註冊在程式退出時調用的函數
signal 處理 POSIX 信號

光常用的模塊就這麼一大堆,確實是很難都記住,記不住也沒關係,當需要用到的時候隨用隨查就可以了。

結語

本篇中主要介紹了模塊化的定義,引入模塊化的方式,模塊的查找順序,常用的內置模塊簡介等內容,通過使用模塊化,能夠更好的實踐模塊化程式設計的思想。但本篇並沒有涉及 package 的概念,會在後續章節講述。

下篇會講述 python 中正則表達式,敬請期待。

參考文檔

  1. python modules
  2. 模塊化程式設計—百度百科
  3. 《代碼大全》
  4. 《Python高手之路》

系列文章列表


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 朋友們,起風了,該“浪”起來了。 今天帶大家“浪”的主題是js的數組去重,總結了幾種方法如下,希望有所幫助,希望同行之間的交流,更希望有大神批評指點!!! 方法1:利用ES6的Set結合Array.from去重 方法二:利用ES5中的Index.Of()方法 方法三:利用數組中filter方法 方法 ...
  • 英文名:Singleton Pattern。英文原話:Ensure a class has only one instance,and provide a global point of access to it。 單例模式的主要作用是確保一個類只有一個實例。 一、實現方式 1.靜態內部類 這是最好 ...
  • 從大學到現在,這本書也許我反反覆復地讀了不下十遍,可是這次終於有了勇氣把他標註為看過,因為直到今天我才自信自己真的理解了裡面所講的架構模式。 對於現在的互聯網時代,所有的開發思想都是強調簡潔,強調“敏捷”,甚至曾經流行一時的OOD竟然有被嫌棄的趨勢 《企業應用架構模式》作者是當今面向對象軟體開發的權 ...
  • 在互聯網產品運營中,有很多小伙伴或許會遇到這樣的困擾:產品好不容易推出來了,流量成本節節攀升,用戶的活躍度、留存度卻持續下降。因此在瞬息萬變的互聯網產品環境中,需要研發接入支付系統來加入商業行為的閉環,支付系統能夠幫助企業更好地實現商業化,利用那些為用戶而生的支付體系產品,實現用戶積累、商業變現。對... ...
  • 引言 之前的文章我們學習了一個集合類 "ArrayList" ,今天講它的一個兄弟 Vector 。 為什麼說是它兄弟呢?因為從容器的構造來說,Vector 簡直就是 ArrayList 的翻版,也是基於數組的數據結構,不同的是,Vector的每個方法都加了 synchronized 修飾符,是線程 ...
  • 前言 開心一刻 過年女婿來岳父家走親戚,當時小舅子主就問:姐夫,你什麼時候能給我姐幸福,讓我姐好好享受生活的美好。你們這輩子不准備買一套大點的房子嗎?姐夫說:現在沒錢啊!不過我有一個美麗可愛的女兒,等長大後找個有錢的老公嫁了,那時我就能和你姐一起住大房子了。岳父不樂意的說了一句:當初我也是這麼認為的 ...
  • Integer是一個看著挺簡單的,其實還是有點不一樣,Integer是一個int的包裝類,它是可以起到緩存作用的,在java基礎里說過它的範圍是(-128-127)在這個返回是有緩存的,不會創建新的Integer對象,並且可以設置它的最大值,通過設置VM參數。 下麵先看一下源碼: 通過設置VM的ja ...
  • 多線程 利用條件變數實現線程安全的隊列 背景:標準STL庫的隊列queue是線程不安全的。 利用條件變數(Condition variable)簡單實現一個線程安全的隊列。 代碼: c++ include include include include include include templat ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...