網站首頁 編程語言 正文
一. 什么是模塊(module)?
在實際應用中,有時程序所要實現功能比較復雜,代碼量也很大。若把所有的代碼都存儲在一個文件中,則不利于代碼的復用和維護。一種更好的方式是將實現不同功能的代碼分拆到多個文件中分別進行存儲,這樣使得結構更加清晰,更易于維護。
為了實現這些需求,Python將一系列相關的代碼組織在一起存儲在一個文件中,這就是 模塊(module)。最常見的模塊是以.py“為后綴的文件(即用Python編寫的代碼文件),文件名就是模塊名。當然模塊還有一些其他的形式,例如”.so"文件、“.dll” 文件等,但初學者幾乎接觸不到。在一個模塊中可以定義變量、函數、類等,也能包含可執行代碼。Python中的模塊可以分成3類:(1)Python內置的模塊;(2)第三方模塊;(3)用戶自定義的模塊。
看一個簡單的例子,我們可以自定義一個加法模塊add,文件名為“add.py”。
#
# @file add.py
#
def add(a,b):
return a + b
然后在當前目錄中,通過import語句導入該模塊,格式為import 模塊名,之后就可以使用模塊中定義的add函數進行運算了。
>>> import add
>>> add.add(3, 5)
>>> 8
注:上圖第二條語句中的第1個add表示的是add模塊,第2個add表示的是該模塊中定義的add函數。
二. 模塊是如何組織的?
Python中包含各種各樣功能的模塊,數量繁多。若把所有模塊都放到一個目錄中則很難使用和維護,例如容易產生模塊名沖突的問題。因此我們需要一種合理的組織方式來提高模塊的結構性和可維護性。Python是通過包來組織模塊的。
什么是包(package)呢?包本質上就是一個目錄(文件夾),目錄名就是包名。 在包中可以包含多個子目錄(子包)或模塊。
例如我們可以將自定義的加法模塊add、減法模塊sub、乘法模塊mul和除法模塊dev組織成一個包arithmetic,包的架構如下圖所示。
再比如在音頻數據處理中,會用到很多模塊來實現對音頻數據的不同處理。我們就可以設計一個包——sound來組織這些模塊,其下面又包含了3個子包effects、filters和formats,分別對應不同類型的功能模塊,包的架構如下所示。
注:可以發現包中通常都包含一個__init__.py文件。在Python3.x中,這并不是必需的,__init__.py文件的作用將在后面進行介紹。
三. 如何導入模塊?
要使用模塊必須先進行導入,導入模塊有兩類方式:
方式一:import …
import […包].模塊 [as 模塊別名]
例如,import add,import arithmetic.add,import sound.filters.equalizerimport 包 [as 包別名]
例如,import arithmetic
方式二:from … import …
from 包.[…包] import 模塊 [as 模塊別名] / *
例如,from arithmetic import add,from arithmetic import *from […包].模塊 import 變量/函數/類 [as 別名]/ *
例如,from arithmetic.add import add,from arithmetic.add import *
四. 每種導入方式有何區別?
上述兩類模塊導入的方式有什么區別呢?我們在實際編程時,該選擇哪種方式導入模塊呢?要回答這個問題,我們就需要了解模塊導入背后的運行機制。在講解這個機制之前,先簡單介紹一下命名空間的概念。
1. 命名空間
命名空間(namespace)是映射到對象的名稱 ,大多使用字典來實現。命名空間是在不同的時刻創建的,且擁有不同的生命周期。在Python語言中,有3類命名空間:內置命名空間、全局命名空間和局部命名空間。
內置命名空間(build-in namespace)
內置命名空間記錄了以下信息:
內置命名空間中最常用的就是內置函數了,如下所示:
內置命名空間在Python解釋器啟動時創建,直至Python解釋器退出都有效。 因此,Python解釋器一旦啟動,所有的內置函數不需要import,就可直接使用。
全局命名空間(global namespace)
用來記錄模塊級的變量、常量、函數、類以及其他導入的模塊,可通過 globals() 函數查看。全局命名空間在讀取模塊定義時創建,通常也會持續到Python解釋器退出。
可以看到,在全局命名空間中已經包含了一些名稱,例如:
__name__
__doc__
__loader__
__spec__
__annotations__
__buitins__
這些名稱都以雙下劃線開頭和結尾,表示這是系統為每個模塊自動生成的。這里重點介紹一下 __name__ 。它用來標識所在模塊的名字,可能有兩種取值:若該模塊是當前正在運行的模塊,則 __nam__ 的取值為 ‘__main__’; 若該模塊不是正在運行的模塊而是通過 import 語句導入的模塊,則 __name__ 的取值為該模塊的名稱。在Python程序中,會經常看到如下語句:
if __name__ == 'main':
? ? 該語句的作用是:導入該模塊時條件不成立,因而不會執行該語句后面的代碼。
局部命名空間(local namespace)
用來記錄函數或類中定義的變量、常量等,可通過 locals() 函數查看。
def func(a):
b = 2
c = a + b
print(locals())
>>> func(3)
{'a': 3, 'b': 2, 'c': 5}
? ? 函數的局部命名空間在調用該函數時創建,在函數返回或拋出不在函數內部處理的異常時銷毀。
當Python解釋器解釋運行程序時,如遇到某個名稱(如變量x)時,就會在所有命名空間中進行查找以確定其所映射的對象。查找的順序如下:
- 查找局部命名空間。若找到,則停止。
- 若存在父函數,則查找父函數的局部命名空間(閉包)。若找到,則停止。
- 查找全局命名空間。若找到,則停止。
- 查找內置命名空間。若找到,則停止;若還找不到,Python將報錯NameError 。
2. import … 的運行機制
import […包].模塊 [as 模塊別名]
這條語句的執行過程包括以下幾個步驟:
(1)判斷要導入的模塊是否已被加載
導入模塊時要分兩種情況處理:第一情況是該模塊之前已經被加載到內存中了;第二種情況時該模塊尚未被加載到內存中。如何判斷是哪種情況呢?這就需要用到數據結構 sys.modules。
sys模塊包含系統級的信息,像正在運行的Python版本(sys.version)、系統級選項、最大允許遞歸的深度(sys.getrecursionlimit() 和 sys.setrecursionlimit() ) 。sys.modules 是一個全局字典,Python程序啟動時就被加載到了內存中。sys.modules記錄當前所有已加載模塊的信息,字典的鍵字就是模塊名,鍵值就是模塊對象。
>>> import sys
>>> sys.modules
{'sys': <module 'sys' (built-in)>, 'builtins': <module 'builtins' (built-in)>, '_frozen_importlib': <module '_frozen_importlib' (frozen)>, '_imp': <module '_imp' (built-in)>, '_thread': <module '_thread' (built-in)>, '_warnings': <module '_warnings' (built-in)>, '_weakref': <module '_weakref' (built-in)>, '_io': <module '_io' (built-in)>, 'marshal': <module 'marshal' (built-in)>, 'posix': <module 'posix' (built-in)>, '_frozen_importlib_external': <module '_frozen_importlib_external' (frozen)>, 'time': <module 'time' (built-in)>, 'zipimport': <module 'zipimport' (frozen)>, '_codecs': <module '_codecs' (built-in)>, 'codecs': <module 'codecs' from '/usr/lib/python3.10/codecs.py'>, 'encodings.aliases': <module 'encodings.aliases' from '/usr/lib/python3.10/encodings/aliases.py'>, 'encodings': <module 'encodings' from '/usr/lib/python3.10/encodings/__init__.py'>, 'encodings.utf_8': <module 'encodings.utf_8' from '/usr/lib/python3.10/encodings/utf_8.py'>, '_signal': <module '_signal' (built-in)>, '_abc': <module '_abc' (built-in)>, 'abc': <module 'abc' from '/usr/lib/python3.10/abc.py'>, 'io': <module 'io' from '/usr/lib/python3.10/io.py'>, '__main__': <module '__main__' (built-in)>, '_stat': <module '_stat' (built-in)>, 'stat': <module 'stat' from '/usr/lib/python3.10/stat.py'>, '_collections_abc': <module '_collections_abc' from '/usr/lib/python3.10/_collections_abc.py'>, 'genericpath': <module 'genericpath' from '/usr/lib/python3.10/genericpath.py'>, 'posixpath': <module 'posixpath' from '/usr/lib/python3.10/posixpath.py'>, 'os.path': <module 'posixpath' from '/usr/lib/python3.10/posixpath.py'>, 'os': <module 'os' from '/usr/lib/python3.10/os.py'>, '_sitebuiltins': <module '_sitebuiltins' from '/usr/lib/python3.10/_sitebuiltins.py'>, 'apport_python_hook': <module 'apport_python_hook' from '/usr/lib/python3/dist-packages/apport_python_hook.py'>, 'sitecustomize': <module 'sitecustomize' from '/usr/lib/python3.10/sitecustomize.py'>, 'site': <module 'site' from '/usr/lib/python3.10/site.py'>, 'readline': <module 'readline' from '/usr/lib/python3.10/lib-dynload/readline.cpython-310-x86_64-linux-gnu.so'>, 'atexit': <module 'atexit' (built-in)>, '_ast': <module '_ast' (built-in)>, 'itertools': <module 'itertools' (built-in)>, 'keyword': <module 'keyword' from '/usr/lib/python3.10/keyword.py'>, '_operator': <module '_operator' (built-in)>, 'operator': <module 'operator' from '/usr/lib/python3.10/operator.py'>, 'reprlib': <module 'reprlib' from '/usr/lib/python3.10/reprlib.py'>, '_collections': <module '_collections' (built-in)>, 'collections': <module 'collections' from '/usr/lib/python3.10/collections/__init__.py'>, 'types': <module 'types' from '/usr/lib/python3.10/types.py'>, '_functools': <module '_functools' (built-in)>, 'functools': <module 'functools' from '/usr/lib/python3.10/functools.py'>, 'contextlib': <module 'contextlib' from '/usr/lib/python3.10/contextlib.py'>, 'enum': <module 'enum' from '/usr/lib/python3.10/enum.py'>, 'ast': <module 'ast' from '/usr/lib/python3.10/ast.py'>, '_opcode': <module '_opcode' from '/usr/lib/python3.10/lib-dynload/_opcode.cpython-310-x86_64-linux-gnu.so'>, 'opcode': <module 'opcode' from '/usr/lib/python3.10/opcode.py'>, 'dis': <module 'dis' from '/usr/lib/python3.10/dis.py'>, 'collections.abc': <module 'collections.abc' from '/usr/lib/python3.10/collections/abc.py'>, 'importlib._bootstrap': <module '_frozen_importlib' (frozen)>, 'importlib._bootstrap_external': <module '_frozen_importlib_external' (frozen)>, 'warnings': <module 'warnings' from '/usr/lib/python3.10/warnings.py'>, 'importlib': <module 'importlib' from '/usr/lib/python3.10/importlib/__init__.py'>, 'importlib.machinery': <module 'importlib.machinery' from '/usr/lib/python3.10/importlib/machinery.py'>, '_sre': <module '_sre' (built-in)>, 'sre_constants': <module 'sre_constants' from '/usr/lib/python3.10/sre_constants.py'>, 'sre_parse': <module 'sre_parse' from '/usr/lib/python3.10/sre_parse.py'>, 'sre_compile': <module 'sre_compile' from '/usr/lib/python3.10/sre_compile.py'>, '_locale': <module '_locale' (built-in)>, 'copyreg': <module 'copyreg' from '/usr/lib/python3.10/copyreg.py'>, 're': <module 're' from '/usr/lib/python3.10/re.py'>, 'token': <module 'token' from '/usr/lib/python3.10/token.py'>, 'tokenize': <module 'tokenize' from '/usr/lib/python3.10/tokenize.py'>, 'linecache': <module 'linecache' from '/usr/lib/python3.10/linecache.py'>, 'inspect': <module 'inspect' from '/usr/lib/python3.10/inspect.py'>, 'rlcompleter': <module 'rlcompleter' from '/usr/lib/python3.10/rlcompleter.py'>}
除了我們自己導入過的模塊,Python在啟動時已經預先加載了一些模塊,其中大多都是內置(build-in)模塊。內置模塊是用C語言編寫的,Python程序員必須依靠他們來實現系統級的功能,例如文件I/O等。內置模塊是Python標準庫的重要組成部分。
字典sys.modules對于加載模塊起到了緩沖的作用,當使用 import 語句導入模塊時,首先會在這個字典中進行查找,確定該模塊是否已被加載到內存中。第一種情況:若模塊已被加載,則只需將最外層包的名字添加到 import 語句所在模塊的局部命名空間中,模塊導入的過程就此結束。 第二種情況:若要導入的模塊尚未被加載,則繼續執行以下步驟。
(2)搜索要導入的模塊
Python解釋器首先會在內置模塊中搜索同名的模塊 (注:所以我們自定義的模塊不應該與內置模塊重名)。若沒有找到,則在sys.path中的目錄中進行搜索。sys.path是模塊查找的路徑列表,初始化為系統環境變量PYTHONPATH。
>>> import sys
>>> sys.path
['', '/home/csl/test/py/2', '/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '/home/csl/.local/lib/python3.10/site-packages', '/usr/local/lib/python3.10/dist-packages', '/usr/lib/python3/dist-packages']
可以發現,sys.path列表的第一項path[0]是包含用于調用Python解釋器的腳本的目錄。如果腳本目錄不可用(例如,交互調用解釋器或從標準輸入讀取腳本),則path[0]是空字符串。path[0]將引導Python首先在當前目錄中進行搜索。
若在當前目錄中沒有找到,則會在sys.path包含其他目錄中依次搜索,這些目錄中包含了已安裝的第三方模塊。若仍然沒有找到,則會報錯ModuleNotFoundError。
(3)加載要導入的模塊
搜索到模塊之后,接下來就是將其加載到內存中。如何進行加載呢?這里舉例進行說明。
現在我們需要在main.py中導入自定義的arithmetic包中的 add 模塊,其目錄結構如下所示。
在main.py中,可以采用語句 “import arithmetic.add“ 實現。該語句進行模塊加載的過程如下:
- 首先運行arithmetic包中的 __init__.py 文件(如果存在的話),該模塊用到的所有對象都收錄到一塊新開辟的內存空間中。創建一個變量指向這個內存空間,用來引用其內容。變量的名字就是包名——arithmetic,從這個意義上說包其實也相當于一個模塊。將arithmetic添加到sys.modules中。將arithmetic添加到main模塊的局部命名空間中。
- 然后運行包arithmetic中要導入的模塊add,該模塊用到的所有對象也收錄到一塊新開辟的內存空間中。創建一個變量指向這個內存空間,用來引用其內容。若給模塊起了別名,變量名就是模塊別名;否則,變量名就是模塊名。這里變量名就是模塊名——add。將變量arithmetic.add 添加到sys.modules中。將add添加到arithmetic(__init__)模塊的局部命名空間中。
下面來驗證一下這個過程,在main.py中添加如下代碼:
#
# @file main.py
#
import arithmetic.add
print(dir(),'\n')
print(dir(arithmetic),'\n')
print(dir(arithmetic.add),'\n')
代碼中的 dir() 是一個內置函數,用于查找模塊定義的名稱,返回的結果是經過排序的字符串列表。
['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'arithmetic']
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'add']
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'add']
可發現確實是將arithmetic 添加到了main模塊的命名空間中,將add添加到了arithmetic的命名空間中。整個過程如下圖所示:
模塊加載結束后,導入的模塊就可以使用了。從上圖也可以發現:在使用導入的模塊中的對象時,前面必須加上包名和模塊名。例如在main.py中使用add模塊中定義的add函數,代碼如下:
#
# @file main.py
#
import arithmetic.add
print(arithmetic.add.add(3,5))
import 包 [as 包別名]
這條語句的執行過程也是類似的。前面說過包本質上就是模塊,導入包其實就是導入包下面的__init__模塊。
注:若包中沒有__init__.py 文件或者該文件為空,則只會將包名或者包別名添加到import語句所在模塊的局部命名空間中,而不會導入包中的其他模塊。
那使用語句 “import 包 [as 包別名]” 導入模塊時 __init__.py 該如何編寫呢?舉個例子,包arithmetic中的add、sub、mul 和 dev四個模塊,分別實現了加、減、乘、除四則運算。現在需要在main.py 文件中同時使用這四種運算,若采用語句“import […包].模塊 [as 模塊別名]”導入模塊,代碼如下:
#
# @file main.py
#
import arithmetic.add
import arithmetic.sub
import arithmetic.mul
import arithmetic.dev
也就是說當需要使用四則運算時,就需要把arithmeitc包中的模塊逐個導入一遍,很麻煩!
可以采用“import 包 [as 包別名]” 導入模塊,在 __init__.py 中添加如下代碼:
#
# @file __init__.py
#
import arithmetic.add
import arithmetic.sub
import arithmetic.mul
import arithmetic.dev
此時,在main.py 文件只需編寫代碼:
#
# @file main.py
#
import arithmetic
__init__.py 文件的作用不止于此。利用__init__.py,可以對外提供類型、變量和接口,對用戶隱藏各個子模塊的實現。一個模塊的實現可能非常復雜,需要用很多個文件,甚至很多子模塊來實現,但用戶可能只需要知道一個類型和接口。就像我們的arithmetic例子中,用戶只需要知道四則運算有add、sub、mul、dev四個接口,并不需要關心它們是怎么實現的,也沒有必要去了解arithmetic中是如何組織各個子模塊的。由于各個子模塊的實現有可能非常復雜,而對外提供的類型和接口有可能非常的簡單,我們就可以通過這個方式來對用戶隱藏實現,同時提供非常方便的使用。
在編寫__init__.py 文件時,應遵循以下原則:(1) 不要污染現有的命名空間。使用模塊的一個目的就是為了避免命名沖突,如果在使用__init__.py時違背這個原則,則是反其道而為之,也沒有使用模塊的必要了。(2)只在__init__.py中編寫必要的代碼,不要做沒必要的運算。
3. from … import … 的運行機制
第二類導入方式 “from … import …” 的運行包括以下步驟:
- 首先也是通過sys.modules判斷要導入的模塊是否已經加載過。
- 若尚未加載,則按照 “內置模塊 --> sys.path路徑列表中包含的模塊” 的順序進行搜索。
- 加載要導入的模塊。
其中,前面兩步與第一種方式 “import …” 是相同的;只是第3步,二者有所區別。因此,接下來只須介紹第3步模塊加載這部分內容,仍用前面的例子進行說明。
from 包.[…包] import 模塊 [as 模塊別名] / *
在main.py中導入自定義的arithmetic包中的 add 模塊,采用這種方式可寫成 “from arithmetic import add”。該語句的模塊加載過程如下:
首先運行arithmetic包中的 __init__.py 文件(如果存在的話),該模塊用到的所有對象都收錄到一塊新開辟的內存空間中。創建一個變量指向這個內存空間,用來引用其內容。變量的名字就是包名——arithmetic。將arithmetic添加到sys.modules中。(注:這里不會將arithmetic添加到main模塊的局部命名空間中。)
然后運行包arithmetic中要導入的模塊add,該模塊用到的所有對象也收錄到一塊新開辟的內存空間中。創建一個變量指向這個內存空間,用來引用其內容。若給模塊起了別名,變量名就是模塊別名;否則,變量名就是模塊名。這里變量名就是模塊名——add。將變量arithmetic.add 添加到sys.modules中。將add添加到main模塊的局部命名空間中。
同樣可以驗證一下這個過程:
#
# @file main.py
#
import from arithmetic import add
print(locals())
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f0f9af417e0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/home/csl/test/py/2/main.py', '__cached__': None, 'add': <module 'arithmetic.add' from '/home/csl/test/py/2/arithmetic/add.py'>}
可以發現該執行后,main模塊的局部命名空間中確實增加了"add"這個名稱,其所對應的就是arithmetic包中的add模塊。因而,在main模塊中,可以直接使用模塊名來引用模塊中的對象。
#
# @file main.py
#
import from arithmetic import add
print(add.add(3,5))
如果要在main中導入arithmetic包中的add、sub、mul、dev 四個模塊,使用 “from … import …” 語句也是可以的。除了逐個進行導入的方法,還可以采用如下方法實現:
(1)在main.py 文件中添加以下代碼:
#
# @file main.py
#
import from arithmetic import *
在包arithmetic中的__init__.py文件中,將變量 __all__ 設置為要導入的模塊列表:
#
# @file __init__.py
#
__all__ = ['add', 'sub', 'mul', 'dev']
__all__ 通常是與 * 配合使用的。若在__init__.py文件中沒有設置__all__變量,語句 “import from arithmetic import *” 僅會執行包arithmetic中的__init__.py文件。
from […包].模塊 import 變量/函數/類 [as 別名]/ *
使用“from … import …” 語句不僅可以精確地從包中導入某些模塊,還可以精確地從模塊中導入某些對象(如變量、函數、類等)。例如在main.py文件中,需要使用arithmetic包里面add模塊中定義的加法函數add(), 就可以寫成“import from arithmetic.add import add” 。該語句會直接將add模塊中的add() 函數的名字直接添加到main模塊的局部命名空間中。
#
# @file main.py
#
import from arithmetic.add import add
print(locals())
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f62f74697e0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/home/csl/test/py/2/main.py', '__cached__': None, 'add': <function add at 0x7f62f74d5fc0>}
因此,在main中可以直接使用函數名add完成加法運算:
#
# @file main.py
#
import from arithmetic.add import add
print(add(3,5))
注:如果要導入一個模塊中所有的對象,可以寫成 “from […包].模塊 import *”
五. 導入模塊時的一些注意事項
1. 絕對導入與相對導入
第四部分在介紹 “import 包 [as 包別名]” 時,說過在main.py 中導入arithmetic中的add、sub、mul、dev四個模塊可以采用如下方式實現:
#
# @file __init__.py
#
import arithmetic.add
import arithmetic.sub
import arithmetic.mul
import arithmetic.dev
#
# @file main.py
#
import arithmetic
其中,__init__.py文件就是使用絕對路徑名來導入模塊的,稱為絕對導入。這種導入方式中,要導入模塊的路徑都是從"根節點"開始的。“根節點的位置”由sys.path中的路徑決定。
在這個例子中,__init__.py 要導入模塊的絕對路徑就是:“sys.path中的當前路徑/arithmetic/add”, “sys.path中的當前路徑/arithmetic/sub” …
與絕對導入相對的是相對導入,即使用相對路徑名導入模塊。在這個例子中,__init__.py 要導入的add 、sub、mul、dev模塊都位于同一個路徑下。因此,__init__.py采用相對導入的代碼如下:
#
# @file __init__.py
#
from . import add
from . import sub
from . import mul
from . import dev
其中, “.” 就表示當前路徑。另外,“..” 表示上一級路徑。
使用相對導入的好處是:只需關心要導入模塊的相對位置。因此,即便將包arithmetic的名字修改,采用相對導入的方式仍然可以正確運行。而若采用絕對導入,則必須同步修改__init__.py的代碼。需要注意的是:采用相對導入的模塊不能在包的內部直接運行(會報錯)。關于相對導入的更多信息,可參考使用相對路徑名導入包中子模塊。
2. 重新加載模塊
導入模塊后,模塊就已經被加載到內存中了,此后若對模塊代碼進行了改動,讀取的內容仍然是內存中原來的結果。此時,需要使用imp.reload()來重新加載先前加載的模塊。
>>> import arithmetic.add
>>> import imp
>>> imp.reload(arithmetic.add)
3. 模塊的循環導入問題
模塊的導入必須是單鏈的,而不能有循環導入,否則就會出錯。
具體原理參考Python 史上最詳解的 導入(import)
六. 參考資料
以上是我學習Python中import語句相關知識的總結(運行環境: 操作系統ubuntu22.04, Python版本 3.10.6),其中可能存在錯誤。在學習的過程中主要參考了以下資料:
Python–模塊與包(https://article.itxueyuan.com/lMj6K)
__init__.py的神奇用法(https://zhuanlan.zhihu.com/p/115350758)
Python 3.x | 史上最詳解的 導入(import)(https://blog.csdn.net/weixin_38256474/article/details/81228492)
Python Cookbook 3rd Edition Documentation(https://python3-cookbook.readthedocs.io/zh_CN/latest/index.html)
Modules(https://docs.python.org/3/tutorial/modules.html)
python 內置命名空間、標準庫、模塊相關概念 (https://www.cnblogs.com/goldsunshine/p/15085333.html)
原文鏈接:https://blog.csdn.net/chenshulong/article/details/128382522
相關推薦
- 2023-04-07 React?Mobx狀態管理工具的使用_React
- 2022-04-06 Go語言實現枚舉的示例代碼_Golang
- 2022-06-13 Python自動化辦公之圖片轉PDF的實現_python
- 2022-04-28 WPF簡介與基礎開發_實用技巧
- 2022-07-21 查看JVM系統參數的默認值
- 2023-06-03 C++一個函數如何調用其他.cpp文件中的函數_C 語言
- 2022-06-18 Elasticsearch之倒排索引及索引操作_python
- 2022-11-08 Python??Pandas教程之使用?pandas.read_csv()?讀取?csv_pytho
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支