91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python 中包/模塊的 `import` 操作代碼

發布時間:2020-10-16 12:26:05 來源:腳本之家 閱讀:163 作者:Byron_XIE 欄目:開發技術

用實例來說明 import 的作用吧。

創建以下包結構。一個文件夾 cookFish/,下面包含兩個文件, __init__.pycookBook.py

為什么取這幾個名字呢?假設我想用 Python 去做和魚相關的菜,這件事情很復雜,所以我給它創建了一個包,名叫cookFish, 既然是包,在它下面必須得創建一個文件__init__.py。燒魚必備條件之一就是菜譜,所以接著創建了 cookBook.py。這幾個文件對我們這次來說就足夠了,所以就沒有再創建其他文件了。

cookFish/
 __init__.py
 cookBook.py

在cookFish/__init__.py中輸入如下代碼:

__version__ = '0.1'
__author__ = 'XIE Byron'
def cookFish_hello():
 print("cookFish_Hello() from cookFish/__init__.py")

cookFish/cookBook.py中輸入如下代碼:

def cookBook_hello():
 print("cookBook_hello() from cookBook.py")

提示:下面的實例都是在 Python 自帶的命令行解釋器(windows+python 3.7)中運行的結果。如果你在其他環境下運行,比如jupyter notebook,輸出會有差異。

"import package-name" 都做了什么?

導入包cookFish。

>>> import cookFish

提示:

如果import時出現錯誤ModuleNotFoundError,如下:

>>> import cookFish
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'cookFish'

建議先將 Python 的當前工作目錄設置為 cookFish 的 父文件夾(就是包含cookFish文件夾的文件夾)。命令如下:

>>> import os
>>> os.chdir(r'path\to\parent\folder\of\cookFish')

用dir操作查看當前命名空間和cookFish命名空間下都有哪些內容。

>>> dir() # 查看當前命名空間下的對象。注意: cookFish 在當前命名空間下。

['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'cookFish', 'os']

>>> dir(cookFish) # 查看 cookFish 命名空間下的對象。

['__author__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', 'cookFish_hello']

其中的的 __author__, __version__, cookFish_hello 是我們定義的,都導入到了 cookFish 的命名空間下。但是cookFish 下的模塊 cookBook.py 沒有被導入。這是因為直接 import cookFish 只運行cookFish文件夾下的 __init__.py 文件,不會運行其他模塊,所以cookBook沒有被導入。

提示:Python 中的模塊指后綴 .py的文件,也叫腳本。包 指包含 __init__.py 文件的一個文件夾,一般還會包含其他模塊。

包/模塊的命名空間

這里講一下我對概念“在cookFish的命名空間下”的理解。

Python 的 import A 會把 A 的Python 代碼運行一遍,并把運行結果放在一個叫A的命名空間下。

提示: 如果 A 是包,A 的 Python 代碼就是 文件夾A下的 __init__.py 中的代碼。 如果 A 是模塊,那么就是文件 A.py 中的代碼。

import B會把 B 的 Python 代碼運行一遍,并把運行結果放在一個叫 B 的命名空間下。假設A和B中都有一個叫X的對象, A 中的X在當前命名空間下叫 A.X,B中的X在當前命名空間下叫 B.X,兩個X在當前命名空間下不重名。

提示: 這里的對象 指 Python 中的變量/屬性,函數,類,實例等等。

比如__version__屬性(或者叫它變量)就在cookFish的命名空間下,我們只能通過 cookFish.__version__ 才能訪問到 __version__,直接輸入 __version__ 訪問不到它,會報錯。

直接輸入__version__ 運行會報如下錯誤:

>>> __version__
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
NameError: name '__version__' is not defined

其他導入包/模塊的方式

如果我們想導入 cookFish 下的模塊 cookBook呢?可以用下面的語法:

>>> import cookFish.cookBook

然后在 cookFish 的命名空間下又多了 cookBook。

>>> dir(cookFish)
['__author__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', 'cookBook', 'cookFish_hello']

然后就能通過全名cookFish.cookBook訪問cookBook.py中的對象了,比如:

>>> cookFish.cookBook.cookBook_hello()
cookBook_hello() from cookBook.py

好長的名字啊,能不能短一點啊?當然可以:

>>> import cookFish.cookBook as cb

然后在當前命名空間下就多了對象 cb:

>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'cb', 'cookFish', 'os']

然后就能通過別名cb來訪問cookBook.py中的對象了,比如:

>>> cb.cookBook_hello()
cookBook_hello() from cookBook.py

那我能不能只導入cookBook_hello()到當前命名空間?當然可以

>>> from cookFish.cookBook import cookBook_hello

然后 cookBook_hello 就被導入到當前命名空間下了:

>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'cb', 'cookBook_hello', 'cookFish', 'os']

然后就能直接訪問 cookBook_hello()了,不用任何前綴:

>>> cookBook_hello()
cookBook_hello() from cookBook.py

“from 包/模塊名 import *” 是導入所有對象嗎?

那我可以一次性導入 cookFish 下的所有模塊、所有包嗎?可以也不可以。

Python 有一個條指令

from 包/模塊名 import *

比如from cookFish import *,給我們的第一感覺是,這條指令是遍歷了 cookFish 下的所有文件,找到這個包下面的所有包和模塊,把他們統統導入到當前命名空間。

但不幸的是,這個操作在windows和Mac系統上不能很好地實現。因為它們的文件系統不能提供準確的文件名大小寫信息。在這兩個平臺上,Python 不知道應該把ECHO.py導入為模塊echo, Echo 還是ECHO,或者其他。(比如windows 95 上面,所有文件名的首字母都會顯示為大寫)。如果Python 把 ECHO.py導入為 模塊Echo,但實際Python代碼中有時按照 echo 使用的,那肯定會報錯。[1]

Python 支持大小寫,Echo和ECHO是兩個不一樣的對象

Python 的唯一的解決辦法是包的作者提供一個明確的包的索引,告訴 Python 在 Python 代碼中如何命名這個模塊。import 語句定義下面一個約定,如果在包的 __init__.py 中定義了一個 __all__ 列表,在 from xxx import * 時,Python 就會把 __all__ 列表中的對象導入。

! 注意:

__all__ 只對 from xxx import * 有影響,對其他 import 操作沒有任何影響

在cookFish/__init__.py中, 我們只把函數 cookFish_hello加入__all__ 中,代碼如下:

__all__ = ['cookFish_hello', ] # added to support `from xxx import *`
__version__ = '0.1'
__author__ = 'XIE Byron'

def cookFish_hello():
  print("cookFish_Hello() from cookFish/__init__.py")

重啟 Python 解釋器,在導入之前,先運行 dir()顯示當前命名空間的對象。

>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'os']

! 注意:

Python 解釋器為了提高運行效率,同一個模塊只會導入一次。一個模塊被導入后,再次運行導入命名不會重新導入。為了顯示from xx import * 的特殊性,所以需要重啟 Python 解釋器(就是關閉 Python 解釋器,然后重新進入)。

然后運行如下:

>>> from cookFish import *

然后輸入 dir() 查看 cookFish_Hello()是否被導入到了當前命名空間.

>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'cookFish_hello', 'os']

可以看到只有在__all__列表中的 cookFish_hello被導入到當前命名空間,其他什么都沒有導入,連cookFish本身也沒有被導入。

所以問題“可以一次性導入 cookFish 下的所有模塊、所有包嗎?“ 的答案是:是否能一次導入,取決于包的作者有沒有把所有子模塊/子包都加入到 __all__列表中。

參考

[1] Built-in Package Support in Python 1.5

版本

[1] version 1.0, released on 2019-04-21

[2] version 1.1, released on 2019-04-21

添加了 Python 命令的輸出。運行工具為windows版本Python(3.7)自帶的命令行解釋器。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

仙游县| 阿拉尔市| 襄城县| 犍为县| 凭祥市| 什邡市| 哈巴河县| 阳原县| 霍邱县| 塔河县| 句容市| 奈曼旗| 德令哈市| 嘉鱼县| 建湖县| 新疆| 扎囊县| 明溪县| 丹巴县| 潢川县| 时尚| 嵊州市| 韩城市| 连南| 铁岭县| 乐安县| 遂宁市| 饶平县| 钦州市| 比如县| 德保县| 濮阳市| 金门县| 平定县| 余庆县| 龙陵县| 青岛市| 朝阳市| 神木县| 济宁市| 普兰店市|