欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python中import語(yǔ)句用法案例講解

 更新時(shí)間:2022年12月29日 15:30:50   作者:Chen_SL  
在實(shí)際應(yīng)用中,有時(shí)程序所要實(shí)現(xiàn)功能比較復(fù)雜,代碼量也很大,若把所有的代碼都存儲(chǔ)在一個(gè)文件中,則不利于代碼的復(fù)用和維護(hù),這篇文章主要介紹了Python中import語(yǔ)句用法詳解,需要的朋友可以參考下

一. 什么是模塊(module)?

在實(shí)際應(yīng)用中,有時(shí)程序所要實(shí)現(xiàn)功能比較復(fù)雜,代碼量也很大。若把所有的代碼都存儲(chǔ)在一個(gè)文件中,則不利于代碼的復(fù)用和維護(hù)。一種更好的方式是將實(shí)現(xiàn)不同功能的代碼分拆到多個(gè)文件中分別進(jìn)行存儲(chǔ),這樣使得結(jié)構(gòu)更加清晰,更易于維護(hù)。

為了實(shí)現(xiàn)這些需求,Python將一系列相關(guān)的代碼組織在一起存儲(chǔ)在一個(gè)文件中,這就是 模塊(module)。最常見的模塊是以.py“為后綴的文件(即用Python編寫的代碼文件),文件名就是模塊名。當(dāng)然模塊還有一些其他的形式,例如”.so"文件、“.dll” 文件等,但初學(xué)者幾乎接觸不到。在一個(gè)模塊中可以定義變量、函數(shù)、類等,也能包含可執(zhí)行代碼。Python中的模塊可以分成3類:(1)Python內(nèi)置的模塊;(2)第三方模塊;(3)用戶自定義的模塊。

看一個(gè)簡(jiǎn)單的例子,我們可以自定義一個(gè)加法模塊add,文件名為“add.py”。

#
# @file add.py
#
def add(a,b):
    return a + b

然后在當(dāng)前目錄中,通過(guò)import語(yǔ)句導(dǎo)入該模塊,格式為import 模塊名,之后就可以使用模塊中定義的add函數(shù)進(jìn)行運(yùn)算了。

>>> import add
>>> add.add(3, 5)
>>> 8

注:上圖第二條語(yǔ)句中的第1個(gè)add表示的是add模塊,第2個(gè)add表示的是該模塊中定義的add函數(shù)。

二. 模塊是如何組織的?

Python中包含各種各樣功能的模塊,數(shù)量繁多。若把所有模塊都放到一個(gè)目錄中則很難使用和維護(hù),例如容易產(chǎn)生模塊名沖突的問(wèn)題。因此我們需要一種合理的組織方式來(lái)提高模塊的結(jié)構(gòu)性和可維護(hù)性。Python是通過(guò)來(lái)組織模塊的。

什么是包(package)呢?包本質(zhì)上就是一個(gè)目錄(文件夾),目錄名就是包名。 在包中可以包含多個(gè)子目錄(子包)或模塊。

例如我們可以將自定義的加法模塊add、減法模塊sub、乘法模塊mul和除法模塊dev組織成一個(gè)包arithmetic,包的架構(gòu)如下圖所示。

在這里插入圖片描述

再比如在音頻數(shù)據(jù)處理中,會(huì)用到很多模塊來(lái)實(shí)現(xiàn)對(duì)音頻數(shù)據(jù)的不同處理。我們就可以設(shè)計(jì)一個(gè)包——sound來(lái)組織這些模塊,其下面又包含了3個(gè)子包effects、filters和formats,分別對(duì)應(yīng)不同類型的功能模塊,包的架構(gòu)如下所示。

在這里插入圖片描述

注:可以發(fā)現(xiàn)包中通常都包含一個(gè)__init__.py文件。在Python3.x中,這并不是必需的,__init__.py文件的作用將在后面進(jìn)行介紹。

三. 如何導(dǎo)入模塊?

要使用模塊必須先進(jìn)行導(dǎo)入,導(dǎo)入模塊有兩類方式:

方式一: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 變量/函數(shù)/類 [as 別名]/ *
例如,from arithmetic.add import add,from arithmetic.add import *

四. 每種導(dǎo)入方式有何區(qū)別?

上述兩類模塊導(dǎo)入的方式有什么區(qū)別呢?我們?cè)趯?shí)際編程時(shí),該選擇哪種方式導(dǎo)入模塊呢?要回答這個(gè)問(wèn)題,我們就需要了解模塊導(dǎo)入背后的運(yùn)行機(jī)制。在講解這個(gè)機(jī)制之前,先簡(jiǎn)單介紹一下命名空間的概念。

1. 命名空間

命名空間(namespace)是映射到對(duì)象的名稱 ,大多使用字典來(lái)實(shí)現(xiàn)。命名空間是在不同的時(shí)刻創(chuàng)建的,且擁有不同的生命周期。在Python語(yǔ)言中,有3類命名空間:內(nèi)置命名空間、全局命名空間和局部命名空間。

內(nèi)置命名空間(build-in namespace)
內(nèi)置命名空間記錄了以下信息:

在這里插入圖片描述

內(nèi)置命名空間中最常用的就是內(nèi)置函數(shù)了,如下所示:

在這里插入圖片描述

內(nèi)置命名空間在Python解釋器啟動(dòng)時(shí)創(chuàng)建,直至Python解釋器退出都有效。 因此,Python解釋器一旦啟動(dòng),所有的內(nèi)置函數(shù)不需要import,就可直接使用。

全局命名空間(global namespace)
用來(lái)記錄模塊級(jí)的變量、常量、函數(shù)、類以及其他導(dǎo)入的模塊,可通過(guò) globals() 函數(shù)查看。全局命名空間在讀取模塊定義時(shí)創(chuàng)建,通常也會(huì)持續(xù)到Python解釋器退出。

在這里插入圖片描述

可以看到,在全局命名空間中已經(jīng)包含了一些名稱,例如:
__name__
__doc__
__loader__
__spec__
__annotations__
__buitins__
這些名稱都以雙下劃線開頭和結(jié)尾,表示這是系統(tǒng)為每個(gè)模塊自動(dòng)生成的。這里重點(diǎn)介紹一下 __name__ 。它用來(lái)標(biāo)識(shí)所在模塊的名字,可能有兩種取值:若該模塊是當(dāng)前正在運(yùn)行的模塊,則 __nam__ 的取值為 ‘__main__’; 若該模塊不是正在運(yùn)行的模塊而是通過(guò) import 語(yǔ)句導(dǎo)入的模塊,則 __name__ 的取值為該模塊的名稱。在Python程序中,會(huì)經(jīng)??吹饺缦抡Z(yǔ)句:

if __name__ ==  'main':

    該語(yǔ)句的作用是:導(dǎo)入該模塊時(shí)條件不成立,因而不會(huì)執(zhí)行該語(yǔ)句后面的代碼。

局部命名空間(local namespace)
用來(lái)記錄函數(shù)或類中定義的變量、常量等,可通過(guò) locals() 函數(shù)查看。

def func(a):
    b = 2
    c = a + b
    print(locals())
>>> func(3)
{'a': 3, 'b': 2, 'c': 5}

    函數(shù)的局部命名空間在調(diào)用該函數(shù)時(shí)創(chuàng)建,在函數(shù)返回或拋出不在函數(shù)內(nèi)部處理的異常時(shí)銷毀。

當(dāng)Python解釋器解釋運(yùn)行程序時(shí),如遇到某個(gè)名稱(如變量x)時(shí),就會(huì)在所有命名空間中進(jìn)行查找以確定其所映射的對(duì)象。查找的順序如下:

  • 查找局部命名空間。若找到,則停止。
  • 若存在父函數(shù),則查找父函數(shù)的局部命名空間(閉包)。若找到,則停止。
  • 查找全局命名空間。若找到,則停止。
  • 查找內(nèi)置命名空間。若找到,則停止;若還找不到,Python將報(bào)錯(cuò)NameError 。

2. import … 的運(yùn)行機(jī)制

import […包].模塊 [as 模塊別名]

這條語(yǔ)句的執(zhí)行過(guò)程包括以下幾個(gè)步驟:

(1)判斷要導(dǎo)入的模塊是否已被加載

導(dǎo)入模塊時(shí)要分兩種情況處理:第一情況是該模塊之前已經(jīng)被加載到內(nèi)存中了;第二種情況時(shí)該模塊尚未被加載到內(nèi)存中。如何判斷是哪種情況呢?這就需要用到數(shù)據(jù)結(jié)構(gòu) sys.modules。

sys模塊包含系統(tǒng)級(jí)的信息,像正在運(yùn)行的Python版本(sys.version)、系統(tǒng)級(jí)選項(xiàng)、最大允許遞歸的深度(sys.getrecursionlimit() 和 sys.setrecursionlimit() ) 。sys.modules 是一個(gè)全局字典,Python程序啟動(dòng)時(shí)就被加載到了內(nèi)存中。sys.modules記錄當(dāng)前所有已加載模塊的信息,字典的鍵字就是模塊名,鍵值就是模塊對(duì)象。

>>> 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'>}

除了我們自己導(dǎo)入過(guò)的模塊,Python在啟動(dòng)時(shí)已經(jīng)預(yù)先加載了一些模塊,其中大多都是內(nèi)置(build-in)模塊。內(nèi)置模塊是用C語(yǔ)言編寫的,Python程序員必須依靠他們來(lái)實(shí)現(xiàn)系統(tǒng)級(jí)的功能,例如文件I/O等。內(nèi)置模塊是Python標(biāo)準(zhǔn)庫(kù)的重要組成部分。

字典sys.modules對(duì)于加載模塊起到了緩沖的作用,當(dāng)使用 import 語(yǔ)句導(dǎo)入模塊時(shí),首先會(huì)在這個(gè)字典中進(jìn)行查找,確定該模塊是否已被加載到內(nèi)存中。第一種情況:若模塊已被加載,則只需將最外層包的名字添加到 import 語(yǔ)句所在模塊的局部命名空間中,模塊導(dǎo)入的過(guò)程就此結(jié)束。 第二種情況:若要導(dǎo)入的模塊尚未被加載,則繼續(xù)執(zhí)行以下步驟。

(2)搜索要導(dǎo)入的模塊
Python解釋器首先會(huì)在內(nèi)置模塊中搜索同名的模塊 (注:所以我們自定義的模塊不應(yīng)該與內(nèi)置模塊重名)。若沒(méi)有找到,則在sys.path中的目錄中進(jìn)行搜索。sys.path是模塊查找的路徑列表,初始化為系統(tǒng)環(huán)境變量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']

可以發(fā)現(xiàn),sys.path列表的第一項(xiàng)path[0]是包含用于調(diào)用Python解釋器的腳本的目錄。如果腳本目錄不可用(例如,交互調(diào)用解釋器或從標(biāo)準(zhǔn)輸入讀取腳本),則path[0]是空字符串。path[0]將引導(dǎo)Python首先在當(dāng)前目錄中進(jìn)行搜索。

若在當(dāng)前目錄中沒(méi)有找到,則會(huì)在sys.path包含其他目錄中依次搜索,這些目錄中包含了已安裝的第三方模塊。若仍然沒(méi)有找到,則會(huì)報(bào)錯(cuò)ModuleNotFoundError。

(3)加載要導(dǎo)入的模塊
搜索到模塊之后,接下來(lái)就是將其加載到內(nèi)存中。如何進(jìn)行加載呢?這里舉例進(jìn)行說(shuō)明。

現(xiàn)在我們需要在main.py中導(dǎo)入自定義的arithmetic包中的 add 模塊,其目錄結(jié)構(gòu)如下所示。

在這里插入圖片描述

在main.py中,可以采用語(yǔ)句 “import arithmetic.add“ 實(shí)現(xiàn)。該語(yǔ)句進(jìn)行模塊加載的過(guò)程如下:

  • 首先運(yùn)行arithmetic包中的 __init__.py 文件(如果存在的話),該模塊用到的所有對(duì)象都收錄到一塊新開辟的內(nèi)存空間中。創(chuàng)建一個(gè)變量指向這個(gè)內(nèi)存空間,用來(lái)引用其內(nèi)容。變量的名字就是包名——arithmetic,從這個(gè)意義上說(shuō)包其實(shí)也相當(dāng)于一個(gè)模塊。將arithmetic添加到sys.modules中。將arithmetic添加到main模塊的局部命名空間中。
  • 然后運(yùn)行包arithmetic中要導(dǎo)入的模塊add,該模塊用到的所有對(duì)象也收錄到一塊新開辟的內(nèi)存空間中。創(chuàng)建一個(gè)變量指向這個(gè)內(nèi)存空間,用來(lái)引用其內(nèi)容。若給模塊起了別名,變量名就是模塊別名;否則,變量名就是模塊名。這里變量名就是模塊名——add。將變量arithmetic.add 添加到sys.modules中。將add添加到arithmetic(__init__)模塊的局部命名空間中。

下面來(lái)驗(yàn)證一下這個(gè)過(guò)程,在main.py中添加如下代碼:

#
# @file main.py
#

import arithmetic.add

print(dir(),'\n')
print(dir(arithmetic),'\n')
print(dir(arithmetic.add),'\n')

代碼中的 dir() 是一個(gè)內(nèi)置函數(shù),用于查找模塊定義的名稱,返回的結(jié)果是經(jīng)過(guò)排序的字符串列表。

['__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'] 

可發(fā)現(xiàn)確實(shí)是將arithmetic 添加到了main模塊的命名空間中,將add添加到了arithmetic的命名空間中。整個(gè)過(guò)程如下圖所示:

模塊加載結(jié)束后,導(dǎo)入的模塊就可以使用了。從上圖也可以發(fā)現(xiàn):在使用導(dǎo)入的模塊中的對(duì)象時(shí),前面必須加上包名和模塊名。例如在main.py中使用add模塊中定義的add函數(shù),代碼如下:

#
# @file main.py
#

import arithmetic.add

print(arithmetic.add.add(3,5))

import 包 [as 包別名]

這條語(yǔ)句的執(zhí)行過(guò)程也是類似的。前面說(shuō)過(guò)包本質(zhì)上就是模塊,導(dǎo)入包其實(shí)就是導(dǎo)入包下面的__init__模塊。

注:若包中沒(méi)有__init__.py 文件或者該文件為空,則只會(huì)將包名或者包別名添加到import語(yǔ)句所在模塊的局部命名空間中,而不會(huì)導(dǎo)入包中的其他模塊。

那使用語(yǔ)句 “import 包 [as 包別名]” 導(dǎo)入模塊時(shí) __init__.py 該如何編寫呢?舉個(gè)例子,包arithmetic中的add、sub、mul 和 dev四個(gè)模塊,分別實(shí)現(xiàn)了加、減、乘、除四則運(yùn)算。現(xiàn)在需要在main.py 文件中同時(shí)使用這四種運(yùn)算,若采用語(yǔ)句“import […包].模塊 [as 模塊別名]”導(dǎo)入模塊,代碼如下:

#
# @file main.py
#
import arithmetic.add
import arithmetic.sub
import arithmetic.mul
import arithmetic.dev

也就是說(shuō)當(dāng)需要使用四則運(yùn)算時(shí),就需要把a(bǔ)rithmeitc包中的模塊逐個(gè)導(dǎo)入一遍,很麻煩!

可以采用“import 包 [as 包別名]” 導(dǎo)入模塊,在 __init__.py 中添加如下代碼:

#
# @file __init__.py
#
import arithmetic.add
import arithmetic.sub
import arithmetic.mul
import arithmetic.dev

此時(shí),在main.py 文件只需編寫代碼:

#
# @file main.py
#
import arithmetic

__init__.py 文件的作用不止于此。利用__init__.py,可以對(duì)外提供類型、變量和接口,對(duì)用戶隱藏各個(gè)子模塊的實(shí)現(xiàn)。一個(gè)模塊的實(shí)現(xiàn)可能非常復(fù)雜,需要用很多個(gè)文件,甚至很多子模塊來(lái)實(shí)現(xiàn),但用戶可能只需要知道一個(gè)類型和接口。就像我們的arithmetic例子中,用戶只需要知道四則運(yùn)算有add、sub、mul、dev四個(gè)接口,并不需要關(guān)心它們是怎么實(shí)現(xiàn)的,也沒(méi)有必要去了解arithmetic中是如何組織各個(gè)子模塊的。由于各個(gè)子模塊的實(shí)現(xiàn)有可能非常復(fù)雜,而對(duì)外提供的類型和接口有可能非常的簡(jiǎn)單,我們就可以通過(guò)這個(gè)方式來(lái)對(duì)用戶隱藏實(shí)現(xiàn),同時(shí)提供非常方便的使用。

在編寫__init__.py 文件時(shí),應(yīng)遵循以下原則:(1) 不要污染現(xiàn)有的命名空間。使用模塊的一個(gè)目的就是為了避免命名沖突,如果在使用__init__.py時(shí)違背這個(gè)原則,則是反其道而為之,也沒(méi)有使用模塊的必要了。(2)只在__init__.py中編寫必要的代碼,不要做沒(méi)必要的運(yùn)算。

3. from … import … 的運(yùn)行機(jī)制

第二類導(dǎo)入方式 “from … import …” 的運(yùn)行包括以下步驟:

  • 首先也是通過(guò)sys.modules判斷要導(dǎo)入的模塊是否已經(jīng)加載過(guò)。
  • 若尚未加載,則按照 “內(nèi)置模塊 --> sys.path路徑列表中包含的模塊” 的順序進(jìn)行搜索。
  • 加載要導(dǎo)入的模塊。

其中,前面兩步與第一種方式 “import …” 是相同的;只是第3步,二者有所區(qū)別。因此,接下來(lái)只須介紹第3步模塊加載這部分內(nèi)容,仍用前面的例子進(jìn)行說(shuō)明。

在這里插入圖片描述

from 包.[…包] import 模塊 [as 模塊別名] / *

在main.py中導(dǎo)入自定義的arithmetic包中的 add 模塊,采用這種方式可寫成 “from arithmetic import add”。該語(yǔ)句的模塊加載過(guò)程如下:

首先運(yùn)行arithmetic包中的 __init__.py 文件(如果存在的話),該模塊用到的所有對(duì)象都收錄到一塊新開辟的內(nèi)存空間中。創(chuàng)建一個(gè)變量指向這個(gè)內(nèi)存空間,用來(lái)引用其內(nèi)容。變量的名字就是包名——arithmetic。將arithmetic添加到sys.modules中。(注:這里不會(huì)將arithmetic添加到main模塊的局部命名空間中。)

然后運(yùn)行包arithmetic中要導(dǎo)入的模塊add,該模塊用到的所有對(duì)象也收錄到一塊新開辟的內(nèi)存空間中。創(chuàng)建一個(gè)變量指向這個(gè)內(nèi)存空間,用來(lái)引用其內(nèi)容。若給模塊起了別名,變量名就是模塊別名;否則,變量名就是模塊名。這里變量名就是模塊名——add。將變量arithmetic.add 添加到sys.modules中。將add添加到main模塊的局部命名空間中。

同樣可以驗(yàn)證一下這個(gè)過(guò)程:

#
# @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'>}

可以發(fā)現(xiàn)該執(zhí)行后,main模塊的局部命名空間中確實(shí)增加了"add"這個(gè)名稱,其所對(duì)應(yīng)的就是arithmetic包中的add模塊。因而,在main模塊中,可以直接使用模塊名來(lái)引用模塊中的對(duì)象。

#
# @file main.py
#

import from arithmetic import add

print(add.add(3,5))

如果要在main中導(dǎo)入arithmetic包中的add、sub、mul、dev 四個(gè)模塊,使用 “from … import …” 語(yǔ)句也是可以的。除了逐個(gè)進(jìn)行導(dǎo)入的方法,還可以采用如下方法實(shí)現(xiàn):
(1)在main.py 文件中添加以下代碼:

#
# @file main.py
#

import from arithmetic import *

在包arithmetic中的__init__.py文件中,將變量 __all__ 設(shè)置為要導(dǎo)入的模塊列表:

#
# @file __init__.py
#
__all__ = ['add', 'sub', 'mul', 'dev']

__all__ 通常是與 * 配合使用的。若在__init__.py文件中沒(méi)有設(shè)置__all__變量,語(yǔ)句 “import from arithmetic import *” 僅會(huì)執(zhí)行包arithmetic中的__init__.py文件。

from […包].模塊 import 變量/函數(shù)/類 [as 別名]/ *

使用“from … import …” 語(yǔ)句不僅可以精確地從包中導(dǎo)入某些模塊,還可以精確地從模塊中導(dǎo)入某些對(duì)象(如變量、函數(shù)、類等)。例如在main.py文件中,需要使用arithmetic包里面add模塊中定義的加法函數(shù)add(), 就可以寫成“import from arithmetic.add import add” 。該語(yǔ)句會(huì)直接將add模塊中的add() 函數(shù)的名字直接添加到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中可以直接使用函數(shù)名add完成加法運(yùn)算:

#
# @file main.py
#

import from arithmetic.add import add
print(add(3,5))

注:如果要導(dǎo)入一個(gè)模塊中所有的對(duì)象,可以寫成 “from […包].模塊 import *

五. 導(dǎo)入模塊時(shí)的一些注意事項(xiàng)

1. 絕對(duì)導(dǎo)入與相對(duì)導(dǎo)入

第四部分在介紹 “import 包 [as 包別名]” 時(shí),說(shuō)過(guò)在main.py 中導(dǎo)入arithmetic中的add、sub、mul、dev四個(gè)模塊可以采用如下方式實(shí)現(xiàn):

在這里插入圖片描述

#
# @file __init__.py
#

import arithmetic.add
import arithmetic.sub
import arithmetic.mul
import arithmetic.dev
#
# @file main.py
#

import arithmetic

其中,__init__.py文件就是使用絕對(duì)路徑名來(lái)導(dǎo)入模塊的,稱為絕對(duì)導(dǎo)入。這種導(dǎo)入方式中,要導(dǎo)入模塊的路徑都是從"根節(jié)點(diǎn)"開始的。“根節(jié)點(diǎn)的位置”由sys.path中的路徑?jīng)Q定。

在這個(gè)例子中,__init__.py 要導(dǎo)入模塊的絕對(duì)路徑就是:“sys.path中的當(dāng)前路徑/arithmetic/add”, “sys.path中的當(dāng)前路徑/arithmetic/sub” …

與絕對(duì)導(dǎo)入相對(duì)的是相對(duì)導(dǎo)入,即使用相對(duì)路徑名導(dǎo)入模塊。在這個(gè)例子中,__init__.py 要導(dǎo)入的add 、sub、mul、dev模塊都位于同一個(gè)路徑下。因此,__init__.py采用相對(duì)導(dǎo)入的代碼如下:

#
# @file __init__.py
#

from . import add
from . import sub
from . import mul
from . import dev

其中, “.” 就表示當(dāng)前路徑。另外,“..” 表示上一級(jí)路徑。

使用相對(duì)導(dǎo)入的好處是:只需關(guān)心要導(dǎo)入模塊的相對(duì)位置。因此,即便將包arithmetic的名字修改,采用相對(duì)導(dǎo)入的方式仍然可以正確運(yùn)行。而若采用絕對(duì)導(dǎo)入,則必須同步修改__init__.py的代碼。需要注意的是:采用相對(duì)導(dǎo)入的模塊不能在包的內(nèi)部直接運(yùn)行(會(huì)報(bào)錯(cuò))。關(guān)于相對(duì)導(dǎo)入的更多信息,可參考使用相對(duì)路徑名導(dǎo)入包中子模塊。

2. 重新加載模塊

導(dǎo)入模塊后,模塊就已經(jīng)被加載到內(nèi)存中了,此后若對(duì)模塊代碼進(jìn)行了改動(dòng),讀取的內(nèi)容仍然是內(nèi)存中原來(lái)的結(jié)果。此時(shí),需要使用imp.reload()來(lái)重新加載先前加載的模塊。

>>> import arithmetic.add
>>> import imp
>>> imp.reload(arithmetic.add)

3. 模塊的循環(huán)導(dǎo)入問(wèn)題

模塊的導(dǎo)入必須是單鏈的,而不能有循環(huán)導(dǎo)入,否則就會(huì)出錯(cuò)。

在這里插入圖片描述

具體原理參考Python 史上最詳解的 導(dǎo)入(import)

六. 參考資料

以上是我學(xué)習(xí)Python中import語(yǔ)句相關(guān)知識(shí)的總結(jié)(運(yùn)行環(huán)境: 操作系統(tǒng)ubuntu22.04, Python版本 3.10.6),其中可能存在錯(cuò)誤。在學(xué)習(xí)的過(guò)程中主要參考了以下資料:

Python–模塊與包(https://article.itxueyuan.com/lMj6K)

__init__.py的神奇用法(https://zhuanlan.zhihu.com/p/115350758)

Python 3.x | 史上最詳解的 導(dǎo)入(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 內(nèi)置命名空間、標(biāo)準(zhǔn)庫(kù)、模塊相關(guān)概念 (https://www.cnblogs.com/goldsunshine/p/15085333.html)

到此這篇關(guān)于Python中import語(yǔ)句用法詳解的文章就介紹到這了,更多相關(guān)Python import語(yǔ)句用法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Django DRF認(rèn)證組件流程實(shí)現(xiàn)原理詳解

    Django DRF認(rèn)證組件流程實(shí)現(xiàn)原理詳解

    這篇文章主要介紹了Django DRF認(rèn)證組件流程實(shí)現(xiàn)原理詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • python實(shí)現(xiàn)錄屏功能(親測(cè)好用)

    python實(shí)現(xiàn)錄屏功能(親測(cè)好用)

    這篇文章主要介紹了使python實(shí)現(xiàn)錄屏功能(親測(cè)好用),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的工作或?qū)W習(xí)具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03
  • Django零基礎(chǔ)入門之模板變量詳解

    Django零基礎(chǔ)入門之模板變量詳解

    這篇文章主要介紹了Django零基礎(chǔ)入門之模板變量詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • Python從入門到精通之Hash函數(shù)的使用詳解

    Python從入門到精通之Hash函數(shù)的使用詳解

    Python提供了強(qiáng)大而靈活的Hash函數(shù),用于在各種應(yīng)用中實(shí)現(xiàn)數(shù)據(jù)存儲(chǔ)、數(shù)據(jù)校驗(yàn)、加密等功能,下面將從入門到精通介紹Python中Hash函數(shù)的使用,感興趣的可以了解一下
    2023-08-08
  • Python實(shí)現(xiàn)Linux中的du命令

    Python實(shí)現(xiàn)Linux中的du命令

    這篇文章主要介紹了Python實(shí)現(xiàn)Linux中簡(jiǎn)單du命令,需要的朋友可以參考下
    2017-06-06
  • Python批量修改圖片分辨率的實(shí)例代碼

    Python批量修改圖片分辨率的實(shí)例代碼

    今天小編就為大家分享一篇Python批量修改圖片分辨率的實(shí)例代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-07-07
  • django認(rèn)證系統(tǒng)實(shí)現(xiàn)自定義權(quán)限管理的方法

    django認(rèn)證系統(tǒng)實(shí)現(xiàn)自定義權(quán)限管理的方法

    今天小編就為大家分享一篇django認(rèn)證系統(tǒng)實(shí)現(xiàn)自定義權(quán)限管理的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-08-08
  • Python3中的多行輸入問(wèn)題

    Python3中的多行輸入問(wèn)題

    這篇文章主要介紹了Python3中的多行輸入問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • python 用所有標(biāo)點(diǎn)符號(hào)分隔句子的示例

    python 用所有標(biāo)點(diǎn)符號(hào)分隔句子的示例

    今天小編就為大家分享一篇python 用所有標(biāo)點(diǎn)符號(hào)分隔句子的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-07-07
  • python中的?sorted()函數(shù)和sort()方法區(qū)別

    python中的?sorted()函數(shù)和sort()方法區(qū)別

    這篇文章主要介紹了python中的?sorted()函數(shù)和sort()方法,首先看sort()方法,sort方法只能對(duì)列表進(jìn)行操作,而sorted可用于所有的可迭代對(duì)象。具體內(nèi)容需要的小伙伴可以參考下面章節(jié)
    2022-02-02

最新評(píng)論