您好,登錄后才能下訂單哦!
任何Python源文件都能以模塊的形式使用,例如:
# spam.py
a = 37
def foo():
print("I'm foo and a is %s" % a)
def bar():
print("I'm bar and I'm calling foo")
class Spam(object):
def grok(self):
print("I'm Spam.grok")
要以模塊的形式加載這段代碼,可以使用import spam語句。首次使用import加載模塊時,它將做3件事:
1) 創建新的命名空間,用作在相應源文件中定義的所有對象的容器。
2) 在新創建的命名空間中執行模塊中包含的代碼。
3) 在調用函數中創建名稱為引用模塊命名空間,這個名稱與模塊的名稱相匹配,例如:
import spam
x = spam.a
spam.foo()
s = spam.Spam()
s.grok()
import執行已加載源的文件中的所有語句。要導入多個模塊,可以為import提供逗號分隔的模塊名稱列表,例如:
import socket, os, re
用于引用模塊的名稱可以使用as限定符進行更改,例如:
import spam as sp
import socket as net
sp.foo()
sp.bar()
net.gethostname()
import語句可以出現在程序中的任何位置,但是每個模塊中的代碼僅加載和執行一次。
?
from語句用于將模塊中的具體定義加載到當前命名空間中。from語句相當于import,但它不會創建一個名稱來引用新創建的模塊命名空間,而是將對模塊中定義的一個或多個對象的引用放到當前命名空間中。例如:
from spam import foo
foo()
spam.foo() # NameError
from語句還會接受用逗號分隔的對象名稱列表,例如:
from spam import(foo, bar, Spam)
另外,as限定符可用于重命名使用from導入的具體對象,例如:
from spam import Spam as Sp
s = Sp()
"*"星號通配符也可用于加載模塊中的所有定義,但以下劃線開頭的定義除外,例如:
from spam import *
form module import 語句只能在模塊最頂層使用。通過定義列表__all__,模塊可以精確控制from spam import \導入的名稱集合,例如:
# spam.py
__all__ = ['bar', 'spam']
使用from導入形式導入定義不會更改定義的作用域規則。函數的全局命名空間始終是定義該函數的模塊,而不是將函數導入并調用該函數的命名空間。
?
加載模塊時,解釋器在sys.path路徑中搜索字典列表。sys.path中的第一個條目通常是空字符串,表示當前正在使用的字典。sys.path中的其他條目可能包含字典名稱、.zip歸檔文件和.egg文件。各個條目在sys.path中列出的順序決順決定了加載模塊時的搜索順序。
可以將一組模塊打包為一個文件,設想創建兩個模塊foo.py和bar.py,并將它們放在一個名為mymodules.zip的zip文件中,就可以以如下方式添加到搜索路徑:
import sys
sys.path.append("mymodules.zip")
import foo, bar
zip文件可以與常規路徑名稱組件混合使用,例如:
sys.path.append("/tmp/modules.zip/lib/python")
從zip中導入需要注意一些限制。首先,只能從歸檔文件中導入.py、.pyw、.pyc和.pyo文件。而且,從歸檔文件加載.py文件時,Python不會建.pyc和.pyo文件,這會導致加載模塊時的性能下降。
?
使用import加載的模塊實際上可分為4個通用類別:
1) 使用Python編寫的代碼
2) 已被編譯為共享庫或DLL的C或C++擴展
3) 包含一組模塊的包
4) 使用C編寫并鏈接到Python解釋器的內置模塊
查看編塊(以foo為例)時,解釋器在sys.path下的每個目錄中搜索以下文件(按搜索順序列出):
1) 目錄foo,它定義了一個包
2) foo.pyd、foo.so、foomodule.so或foomodule.dll(已編譯的擴展)
3) foo.pyo(只適用于使用了-O或-OO選項時)
4) foo.pyc
5) foo.py(Windows上還會查找.pyw文件)
對于.py文件,首次導入模塊時,它會被編譯為字節碼并作為.pyc文件寫回磁盤。在后續導入中,解釋器將加載這段預編譯的字節碼,除非.py文件的修改日期要更新一些。.pyc文件與解釋器的-O選項結合,文件已刪除了行號、斷言和其他調試信息的字節碼。如果指定-OO選項,還會從文件中刪除文檔字符串。
只有使用import語句才能將文件自動編譯為.pyc和.pyo文件。另外,如果包含模塊的.py文件的目錄不允許寫入,將不會創建這些文件。解釋器的-B選項也可以禁止生成這些文件。
如果存在.pyc和.pyo文件,則可以沒有相應的.py文件。但即使沒有提供源文件,仍然可以檢查并找到大量細節。并且,為某個Python版本生成的.pyc文件可能不適用于其他的Python版本。
?
包可用于將一組模塊分組到一個常見的包名稱下,這有助于解決不同應用程序中使用的模塊名稱之間的命名空間沖突問題。包是通過使用與其相同的名稱創建目錄,并在該目錄中創建文件__init__.py來創建的。可以將如下形式組織一個包:
Graphics/
__init__.py
Primitive/
__init__.py
lines.py
fill.py
text.py
Graph3d/
__init__.py
plot2d.py
Graph4d/
__init__.py
plot3d.py
png.py
tiff.py
jpeg.py
import語句用于通過多種方式從包中加載模塊:
1) import Graphics.Primitive.fill
2) from Graphics.Primitive import fill
3) from Graphics.Primitive.fill import floodfill
只要第一次導入包中的任何部分,就會執行__init__.py中的代碼。這個文件可以為空。在import語句執行期間,遇到的所有__init__.py文件都會執行。因此,之前示例中的import Graphics.Primitive.fill語句將會首先執行Graphics目錄中的__init__.py文件,然后執行Primitive目錄中的__init__.py文件。
處理以下這條語句時需注意:
from Graphics.Primitive import *
使用該語句希望將與某個包相關聯的所有子模塊導入到當前命名空間中,但是該語句只會導入在Primitive目錄的__init__.py文件中定義的所有名稱。這種行為可以通過定義列表__all__來修改,例如:
# Graphics/Primitive/__init__.py
__all__ = ["lines", "text", "fill"]
如果想要導入同一個包中的其他子模塊時,可以使用相對導入,例如:
# fill.py
from . import lines
相對導入也可以加載同一個包的不同目錄中包含的子模塊,例如:
# plot2d.py
from ..Primitives import lines
相對導入只能命名用from module import symbol形式的導入語句來指定。因此import ..Primitives.lines或import .lines這樣的語句在語法上是不對的。
最后,Python導入一個包時,它將定義特殊變量__path__,該變量包含一個目錄列表,查找包的子模塊時將搜索這個列表。__path__可通過__init__.py文件中包含的代碼訪問,最初包含的一項具有包的目錄包稱。如果有必要,包可以向__path__列表提供更多目錄,更改查找子模塊時使用的搜索路徑。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。