
來源:麥叔編程
作者:麥叔
Python必備核心技能 - 模塊module(內容超詳細,舉例說明很容易懂)
Python模塊和包是和變量,函數,類同等重要的基礎的基礎。因為它們是Python組織程序的方式。掌握不好,你很難學習和理解新的知識,會處處碰壁。是掌握Python必備的核心技能。
在硬核Python私教班課程中,我把所有關鍵技能總結為Python 36技,模塊和包是其中之一。如果你想快速系統的學習Python,建立辦公自動化,數據分析等實戰技能,需要有專業老師指導你解決問題,可以考慮麥叔私教課,物美價廉。有興趣咨詢maishu1024。
本文詳細講解了:
模塊化編程是指將編程任務分解為單獨的,較小的,更易于管理的子任務或模塊的過程。然后可以像構建模塊
一樣將各個模塊拼湊在一起以創建更大的應用程序。
程序模塊化代碼有幾個優點:
函數,模塊和包都是Python中促進代碼模塊化的機制。
在Python中定義模塊的方式有三種:
在這三種情況下,訪問模塊內容的方式都是相同的: 使用import語句。
本文重點主要放在用Python編寫的模塊上。用Python編寫的模塊很酷的一點是,它很容易。
你所需要做的就是創建一個包含合法Python代碼的文件,然后給該文件一個后綴名為.py的名稱。就是這樣!不需要特殊的語法或魔法。你就創建了一個模塊。
例如,假設你創建了一個名為mod.py的文件,其中包含以下內容:
s = "這是我的第一個模塊,我是麥叔,喜歡請關注我." a = [100, 200, 300] def foo(arg):
print(f'arg = {arg}') class Foo: pass
mod.py中定義了幾個對象:
假設mod.py保存在你電腦上的某一個位置,這些對象可以通過如下方式導入模塊來訪問:
>>> import mod >>> print(mod.s)
這是我的第一個模塊,我是麥叔,喜歡請關注我. >>> mod.a
[100, 200, 300] >>> mod.foo(['你好', '我好', '大家好'])
arg = ['你好', '我好', '大家好'] >>> x = mod.Foo() >>> x
<mod.Foo object at 0x03C181F0>
繼續上面的例子,讓我們看看當Python執行語句時會發生什么:
import mod
當解釋器執行上面的import語句時,它會依次去下面的目錄搜索mod.py,搜索不到就報錯:
可以通過sys.path來得到所有搜索路徑。
>>> import sys >>> sys.path
['', 'C:\Users\maishu\Documents\Python\doc', 'C:\Python36\Lib\idlelib', 'C:\Python36\python36.zip',
'C:\Python36\DLLs', 'C:\Python36\lib', 'C:\Python36', 'C:\Python36\lib\site-packages']
注意:sys.path 和你的python環境有關。上面的代碼在你的電腦上看起來會有些許不同。
因此,要確保找到你的模塊,你需要執行以下操作之一:
實際上還有一個額外的選項:你可以將模塊文件放在你選擇的任何目錄中,然后臨時修改sys.path,以便包含該目錄。例如,
在這種情況下,你可以把mod.py放在目錄C:Usersmaishu中,然后使用以下代碼:
>>> sys.path.append(r'C:Usersmaishu')
>>> sys.path
['', 'C:\Users\maishu\Documents\Python\doc', 'C:\Python36\Lib\idlelib', 'C:\Python36\python36.zip',
'C:\Python36\DLLs', 'C:\Python36\lib', 'C:\Python36', 'C:\Python36\lib\site-packages', 'C:\Users\maishu']
>>> import mod
一旦模塊被導入,你就可以通過模塊的__file__屬性來確定它被找到的位置:
>>> import mod >>> mod.__file__ 'C:\Users\maishu\mod.py' >>> import re >>> re.__file__ 'C:\Python36\lib\re.py'
最簡單的形式是上面所示的:
import <module_name>
請注意,這種簡單的形式只是引用了模塊本身,模塊內的東西并沒有直接引入,不能直接用名字訪問,而要通過模塊.變量的形式。
模塊會創建一個單獨的名稱空間,防止和別的模塊發生沖突。這樣就能以模塊名作為前綴,通過點訪問模塊內的東西,如下所示。
在下列import語句之后,mod被引入到本文件中。因此,可以引用mod:
>>> import mod >>> mod
<module 'mod' from 'C:\Users\maishu\Documents\Python\doc\mod.py'>
但是s和foo仍然在屬于mod內部的變量和函數,不能直接使用:
>>> s NameError: name 's' is not defined >>> foo('quux') NameError: name 'foo' is not defined
必須加上mod前綴才可以:
>>> mod.s 'If Comrade Napoleon says it, it must be right.' >>> mod.foo('quux')
arg = quux
幾個用逗號分隔的模塊可以在一個import語句中指定:
import <module_name>[, <module_name> ...]
import語句的另一種形式允許將模塊中的單個對象直接導入:
from <module_name> import <name(s)>
執行上面的語句后, 可以在不使用前綴的調用者環境中被引用:
>>> from mod import s, foo >>> s '這是我的第一個模塊,我是麥叔,喜歡請關注我.' >>> foo('你好')
arg = 你好 >>> from mod import Foo >>> x = Foo() >>> x
<mod.Foo object at 0x02E3AD50>
因為這種形式的導入將對象名稱直接引入當前文件,任何已經存在的具有相同名稱的對象都將被覆蓋:
>>> a = ['foo', 'bar', 'baz'] >>> a
['foo', 'bar', 'baz'] >>> from mod import a >>> a
[100, 200, 300]
甚至可以一下子不加區別地從一個模塊中導入所有內容:
from <module_name> import *
這將把模塊中的所有對象的名稱引入當前文件,但不包括以下劃線(_)開頭的內容。
例如:
>>> from mod import *
>>> s '這是我的第一個模塊,我是麥叔,喜歡請關注我.' >>> a
[100, 200, 300] >>> foo
<function foo at 0x03B449C0> >>> Foo
<class 'mod.Foo'>
在大規模的項目中并不推薦這樣做。這有一點危險,因為這會在引入全部名稱。除非你對它們都很了解,并且確信不會有沖突,
否則你很有可能會無意中覆蓋現有的變量。然而,當你只是為了測試或學習目的而使用交互式解釋器時,此語法非常方便,
因為它可以讓你快速訪問模塊所提供的所有內容,而無需大量輸入。
也可以導入單獨的對象,并且給它設置一個別名:
from <module_name> import <name> as <alt_name>[, <name> as <alt_name> …]
這使得可以直接將名稱引入,但避免與之前存在的名稱沖突:
>>> s = 'foo' >>> a = ['foo', 'bar', 'baz'] >>> from mod import s as string, a as alist >>> s 'foo' >>>
string '這是我的第一個模塊,我是麥叔,喜歡請關注我.' >>> a
['foo', 'bar', 'baz'] >>> alist
[100, 200, 300]
你也可以用這種方式導入整個模塊:
import <module_name> as <alt_name>
>>> import mod as my_module >>> my_module.a
[100, 200, 300] >>> my_module.foo('qux')
arg = qux
模塊內容也可以從函數中導入。在這種情況下,模塊只有在函數被調用才會被導入:
>>> def bar():
... from mod import foo
... foo('corge')
... >>> bar()
arg = corge
然而,Python3不允許從函數內部使用import *:
>>> def bar():
... from mod import *
... SyntaxError: import * only allowed at module level
最后,帶有except ImportError子句的try語句可以用來防止失敗的導入嘗試:
>>> try:
... # Non-existent module ... import baz
... except ImportError:
... print('Module not found')
...
Module not found
>>> try:
... # Existing module, but non-existent object ... from mod import baz
... except ImportError:
... print('Object not found in module')
...
Object not found in module
內置函數dir()返回一個模塊中定義的所有名稱列表(函數,全局變量等)。如果沒有參數,它會在當前局部符號表中生成一個按字母排序的名稱列表:
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__'] >>> qux = [1, 2, 3, 4, 5] >>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'qux'] >>> class Bar(): ... pass
... >>> x = Bar() >>> dir()
['Bar', '__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'qux', 'x']
請注意上面對dir()的第一次調用是如何列出幾個已經在命名空間中的名稱的。當定義了新的名稱(qux, Bar, x)時,它們會出現在后續的dir()調用中。
這對于確定import語句到底給命名空間添加了什么是很有用的:
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__'] >>> import mod >>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'mod'] >>> mod.s 'If
Comrade Napoleon says it, it must be right.' >>> mod.foo([1, 2, 3])
arg = [1, 2, 3] >>> from mod import a, Foo >>> dir()
['Foo', '__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'mod'] >>> a
[100, 200, 300] >>> x = Foo() >>> x
<mod.Foo object at 0x002EAD50> >>> from mod import s as string >>> dir()
['Foo', '__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'mod',
'string', 'x'] >>> string 'If Comrade Napoleon says it, it must be right.'
當給dir()一個模塊名的參數時,dir()列出在該模塊中定義的名稱:
>>> import mod >>> dir(mod)
['Foo', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'foo', 's']
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__'] >>> from mod import *
>>> dir()
['Foo', '__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'foo', 's']
任何包含模塊的.py文件本質上也是一個Python腳本,沒有任何理由不能像Python腳本那樣執行它。
下面是mod.py的定義:
mod.py
s = "If Comrade Napoleon says it, it must be right." a = [100, 200, 300] def foo(arg): print(f'arg = {arg}') class Foo: pass
這可以作為一個腳本運行:
C:UsersmaishuDocuments>python mod.py C:UsersmaishuDocuments>
沒有錯誤,所以它顯然是有效的。當然,這不是很有趣。就像它寫的那樣,它只定義對象。它不會對它們做任何事情,也不會生成任何輸出。
讓我們修改一下上面的Python模塊,這樣當它作為腳本運行時就會生成一些輸出:
mod.py
s = "If Comrade Napoleon says it, it must be right." a = [100, 200, 300] def foo(arg):
print(f'arg = {arg}') class Foo: pass print(s)
print(a)
foo('quux')
x = Foo()
print(x)
現在應該更有趣了:
C:UsersmaishuDocuments>python mod.py If Comrade Napoleon says it, it must be right.
[100, 200, 300] arg = quux <__main__.Foo object at 0x02F101D0>
不幸的是,現在它也會在作為模塊導入時生成輸出:
>>> import mod If Comrade Napoleon says it, it must be right.
[100, 200, 300] arg = quux
<mod.Foo object at 0x0169AD50>
這可能不是你想要的。模塊在導入時通常不會生成輸出。
如果能夠區分文件是作為模塊加載的,還是作為獨立腳本運行的,不是很好嗎?
這當然是可以做到的!
當.py文件作為模塊導入時,Python將特殊的變量__name__設置為模塊的名稱。但是,如果一個文件作為一個獨立的腳本運行,
__name__被設置為字符串'__main__'?;谶@個,你可以辨別哪種情況是在運行時發生的,并相應地改變行為:
mod.py
s = "If Comrade Napoleon says it, it must be right." a = [100, 200, 300] def foo(arg):
print(f'arg = {arg}') class Foo: pass if (__name__ == '__main__'):
print('Executing as standalone script')
print(s)
print(a)
foo('quux')
x = Foo()
print(x)
現在,如果你作為一個腳本運行,你會得到輸出:
C:UsersmaishuDocuments>python mod.py
Executing as standalone script
If Comrade Napoleon says it, it must be right.
[100, 200, 300]
arg = quux
<__main__.Foo object at 0x03450690>
但如果你以模塊的形式導入,不會有輸出:
>>> import mod >>> mod.foo('grault')
arg = grault
為了測試模塊中包含的功能,模塊通常被設計為能夠作為獨立的腳本運行。這被稱為單元測試。例如,
假設你已經創建了一個包含階乘函數的模塊fact.py,如下所示:
fact.py
def fact(n): return 1 if n == 1 else n * fact(n-1) if (__name__ == '__main__'):
import sys
if len(sys.argv) > 1:
print(fact(int(sys.argv[1])))
可以將該文件視為一個模塊,并導入fact()函數:
>>> from fact import fact >>> fact(6) 720
但它也可以通過在命令行中傳遞一個整數參數來獨立運行,以進行測試:
C:UsersmaishuDocuments>python fact.py 6 720
為了提高效率,一個模塊在每次解釋器會話中只加載一次。這對于函數和類定義來說很好,它們通常構成模塊內容的大部分。
但是模塊也可以包含可執行語句,通常用于初始化。請注意,這些語句只會在第一次導入模塊時執行。
考慮下面的mod.py文件:
mod.py
a = [100, 200, 300] print('a =', a)
>>> import mod
a = [100, 200, 300] >>> import mod >>> import mod >>> mod.a
[100, 200, 300]
print()只有在第一次導入模塊時執行,不會在后續導入中執行。
如果你對模塊做了更改并需要重新加載它,你需要重新啟動解釋器或使用模塊importlib中的重載函數: reload()
>>> import mod
a = [100, 200, 300] >>> import mod >>> import importlib >>> importlib.reload(mod)
a = [100, 200, 300]
<module 'mod' from 'C:\Users\maishu\Documents\Python\doc\mod.py'>
數據分析咨詢請掃描二維碼
若不方便掃碼,搜微信號:CDAshujufenxi
CDA數據分析師證書考試體系(更新于2025年05月22日)
2025-05-26解碼數據基因:從數字敏感度到邏輯思維 每當看到超市貨架上商品的排列變化,你是否會聯想到背后的銷售數據波動?三年前在零售行 ...
2025-05-23在本文中,我們將探討 AI 為何能夠加速數據分析、如何在每個步驟中實現數據分析自動化以及使用哪些工具。 數據分析中的AI是什么 ...
2025-05-20當數據遇見人生:我的第一個分析項目 記得三年前接手第一個數據分析項目時,我面對Excel里密密麻麻的銷售數據手足無措。那些跳動 ...
2025-05-20在數字化運營的時代,企業每天都在產生海量數據:用戶點擊行為、商品銷售記錄、廣告投放反饋…… 這些數據就像散落的拼圖,而相 ...
2025-05-19在當今數字化營銷時代,小紅書作為國內領先的社交電商平臺,其銷售數據蘊含著巨大的商業價值。通過對小紅書銷售數據的深入分析, ...
2025-05-16Excel作為最常用的數據分析工具,有沒有什么工具可以幫助我們快速地使用excel表格,只要輕松幾步甚至輸入幾項指令就能搞定呢? ...
2025-05-15數據,如同無形的燃料,驅動著現代社會的運轉。從全球互聯網用戶每天產生的2.5億TB數據,到制造業的傳感器、金融交易 ...
2025-05-15大數據是什么_數據分析師培訓 其實,現在的大數據指的并不僅僅是海量數據,更準確而言是對大數據分析的方法。傳統的數 ...
2025-05-14CDA持證人簡介: 萬木,CDA L1持證人,某電商中廠BI工程師 ,5年數據經驗1年BI內訓師,高級數據分析師,擁有豐富的行業經驗。 ...
2025-05-13CDA持證人簡介: 王明月 ,CDA 數據分析師二級持證人,2年數據產品工作經驗,管理學博士在讀。 學習入口:https://edu.cda.cn/g ...
2025-05-12CDA持證人簡介: 楊貞璽 ,CDA一級持證人,鄭州大學情報學碩士研究生,某上市公司數據分析師。 學習入口:https://edu.cda.cn/g ...
2025-05-09CDA持證人簡介 程靖 CDA會員大咖,暢銷書《小白學產品》作者,13年頂級互聯網公司產品經理相關經驗,曾在百度、美團、阿里等 ...
2025-05-07相信很多做數據分析的小伙伴,都接到過一些高階的數據分析需求,實現的過程需要用到一些數據獲取,數據清洗轉換,建模方法等,這 ...
2025-05-06以下的文章內容來源于劉靜老師的專欄,如果您想閱讀專欄《10大業務分析模型突破業務瓶頸》,點擊下方鏈接 https://edu.cda.cn/g ...
2025-04-30CDA持證人簡介: 邱立峰 CDA 數據分析師二級持證人,數字化轉型專家,數據治理專家,高級數據分析師,擁有豐富的行業經驗。 ...
2025-04-29CDA持證人簡介: 程靖 CDA會員大咖,暢銷書《小白學產品》作者,13年頂級互聯網公司產品經理相關經驗,曾在百度,美團,阿里等 ...
2025-04-28CDA持證人簡介: 居瑜 ,CDA一級持證人國企財務經理,13年財務管理運營經驗,在數據分析就業和實踐經驗方面有著豐富的積累和經 ...
2025-04-27數據分析在當今信息時代發揮著重要作用。單因素方差分析(One-Way ANOVA)是一種關鍵的統計方法,用于比較三個或更多獨立樣本組 ...
2025-04-25CDA持證人簡介: 居瑜 ,CDA一級持證人國企財務經理,13年財務管理運營經驗,在數據分析就業和實踐經驗方面有著豐富的積累和經 ...
2025-04-25