Python入門六模組的使用
您已經瞭解瞭如何通過定義一次函式來重用程式中的程式碼。如果您想在您編寫的其他程式中重用許多函式,該怎麼辦?您可能已經猜到,答案是模組。
有各種編寫模組的方法,但最簡單的方法是建立一個.py
包含函式和變數的副檔名的檔案。
另一種方法是用編寫Python直譯器本身的本機語言編寫模組。例如,您可以使用C程式語言編寫模組,在編譯時,可以在使用標準Python直譯器時從Python程式碼中使用它們。
可以通過其他程式匯入模組以利用其功能。這也是我們如何使用Python標準庫的方法。首先,我們將瞭解如何使用標準庫模組。
示例(另存為module_using_sys.py
):
import sys
print('The command line arguments are:')
for i in sys.argv:
print(i)
print('\n\nThe PYTHONPATH is', sys.path, '\n')
輸出:
$ python module_using_sys.py we are arguments # each arg is separated by white space
The command line arguments are:
module_using_sys.py
we
are
arguments
The PYTHONPATH is ['/tmp/py',
# many entries here, not shown here
'/Library/Python/2.7/site-packages',
'/usr/local/lib/python2.7/site-packages']
這個怎麼運作
首先,我們匯入了sys
使用該模組import
宣告。基本上,這轉化為我們告訴Python我們想要使用這個模組。該sys
模組包含與Python直譯器及其環境(即系統)相關的功能。
當Python執行import sys
語句時,它會查詢sys
模組。在這種情況下,它是內建模組之一,因此Python知道在哪裡找到它。
如果它不是一個已編譯的模組,即用Python編寫的模組,那麼Python直譯器將在其sys.path
變數中列出的目錄中搜索它。如果找到該模組,則執行該模組正文中的語句,並使模組可供您使用。請注意,初始化僅在我們第一次匯入模組時完成。
使用點分表示法訪問模組中的argv
sys
sys.argv
sys
argv
該sys.argv
變數是一個列表字串(列表中詳細說明一個的後面的章節)。具體來說,它sys.argv
包含命令列引數列表,即使用命令列傳遞給程式的引數。
如果使用IDE編寫和執行這些程式,請查詢在選單中為程式指定命令列引數的方法。
這裡,當我們執行時python module_using_sys.py we are arguments
,我們module_using_sys.py
使用python
命令執行模組,接下來的其他內容是傳遞給程式的引數。Python將命令列引數儲存在sys.argv
變數中供我們使用。
請記住,執行的指令碼的名稱始終是sys.argv
列表中的第一個元素。所以,在這種情況下,我們將'module_using_sys.py'
as sys.argv[0]
,'we'
as sys.argv[1]
,'are'
as sys.argv[2]
和'arguments'
as sys.argv[3]
。請注意,Python從0開始計數,而不是1。
將sys.path
包含其中輸入模組的目錄名的列表。注意的是,在第一個字串sys.path
是空的-這個空的字串表示當前目錄也是一部分sys.path
是相同PYTHONPATH
的環境變數。這意味著您可以直接匯入位於當前目錄中的模組。否則,您必須將模組放在其中一個目錄中sys.path
。
請注意,當前目錄是啟動程式的目錄。執行import os; print(os.getcwd())
以查詢程式的當前目錄。
位元組編譯的.pyc檔案
匯入模組是一個相對昂貴的事情,因此Python做了一些技巧,使其更快。一種方法是使用擴充套件建立位元組編譯的檔案,擴充套件.pyc
是Python將程式轉換為的中間形式(請記住Python如何工作的介紹部分?)。.pyc
當您下次從另一個程式匯入模組時,此檔案很有用 - 由於匯入模組所需的部分處理已經完成,因此速度會快得多。此外,這些位元組編譯的檔案與平臺無關。
注意:這些.pyc
檔案通常與相應的.py
檔案在同一目錄中建立。如果Python沒有寫入該目錄中檔案的許可權,則不會建立.pyc
檔案。
from..import語句
如果要將argv
變數直接匯入程式(以避免sys.
每次都為其鍵入),則可以使用該from sys import argv
語句。
警告:通常,請避免使用該
from..import
語句,import
而是使用該語句。這是因為您的程式將避免名稱衝突並且更具可讀性。
例:
from math import sqrt
print("Square root of 16 is", sqrt(16))
一個模組 __name__
每個模組都有一個名稱,模組中的語句可以找出其模組的名稱。這對於確定模組是獨立執行還是正在匯入的特定目的非常方便。如前所述,當第一次匯入模組時,它包含的程式碼將被執行。我們可以使用它來使模組以不同的方式執行,具體取決於它是單獨使用還是從另一個模組匯入。這可以使用__name__
模組的屬性來實現。
示例(另存為module_using_name.py
):
if __name__ == '__main__':
print('This program is being run by itself')
else:
print('I am being imported from another module')
輸出:
$ python module_using_name.py
This program is being run by itself
$ python
>>> import module_using_name
I am being imported from another module
>>>
這個怎麼運作
每個Python模組都有自己的__name__
定義。如果是這樣'__main__'
,則意味著模組由使用者獨立執行,我們可以採取適當的措施。
製作自己的模組
建立自己的模組很簡單,你一直在做這些!這是因為每個Python程式也是一個模組。你只需要確保它有一個.py
副檔名。以下示例應該清楚說明。
示例(另存為mymodule.py
):
def say_hi():
print('Hi, this is mymodule speaking.')
__version__ = '0.1'
以上是一個示例模組。正如您所看到的,與我們通常的Python程式相比,它沒有什麼特別之處。接下來我們將看到如何在我們的其他Python程式中使用此模組。
請記住,模組應該放在與我們匯入它的程式相同的目錄中,或者放在其中一個目錄中sys.path
。
另一個模組(另存為mymodule_demo.py
):
import mymodule
mymodule.say_hi()
print('Version', mymodule.__version__)
輸出:
$ python mymodule_demo.py
Hi, this is mymodule speaking.
Version 0.1
這個怎麼運作
請注意,我們使用相同的點分表示法來訪問模組的成員。Python可以很好地重用相同的符號來賦予它獨特的“Pythonic”感覺,這樣我們就不必繼續學習新的方法來做事。
這是一個使用from..import
語法的版本(另存為mymodule_demo2.py
):
from mymodule import say_hi, __version__
say_hi()
print('Version', __version__)
輸出與輸出mymodule_demo2.py
相同mymodule_demo.py
。
請注意,如果__version__
在匯入mymodule的模組中已經聲明瞭名稱,則會發生衝突。這也可能是因為每個模組通常使用此名稱宣告其版本號。因此,總是建議您更喜歡該import
語句,即使它可能會使您的程式更長一些。
你也可以使用:
from mymodule import *
這將匯入所有公共名稱,例如say_hi
但不會匯入,__version__
因為它以雙下劃線開頭。
警告:請記住,您應該避免使用import-star,即
from mymodule import *
。
Python的禪宗
Python的指導原則之一是“明確比隱含更好”。
import this
在Python中執行以瞭解更多資訊。
該dir
功能
內建dir()
函式返回物件定義的名稱列表。如果物件是模組,則此列表包括在該模組內定義的函式,類和變數。
此函式可以接受引數。如果引數是模組的名稱,則該函式返回該指定模組的名稱列表。如果沒有引數,則該函式返回當前模組的名稱列表。
例:
$ python
>>> import sys
# get names of attributes in sys module
>>> dir(sys)
['__displayhook__', '__doc__',
'argv', 'builtin_module_names',
'version', 'version_info']
# only few entries shown here
# get names of attributes for current module
>>> dir()
['__builtins__', '__doc__',
'__name__', '__package__', 'sys']
# create a new variable 'a'
>>> a = 5
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'sys', 'a']
# delete/remove a name
>>> del a
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'sys']
這個怎麼運作
首先,我們看到dir
匯入sys
模組的用法。我們可以看到它包含的巨大屬性列表。
接下來,我們使用該dir
函式而不向其傳遞引數。預設情況下,它返回當前模組的屬性列表。請注意,匯入的模組列表也是此列表的一部分。
為了觀察dir
實際操作,我們定義一個新變數a
併為其賦值,然後檢查dir
並觀察到同名列表中還有一個附加值。我們使用del
語句刪除當前模組的變數/屬性,並且更改將再次反映在dir
函式的輸出中。
關於以下內容的註釋del
:此語句用於刪除變數/名稱,並且在語句執行後,在這種情況下del a
,您無法再訪問該變數a
- 就好像它之前從未存在過一樣。
請注意,該dir()
函式適用於任何物件。例如,執行(字串)類dir(str)
的屬性str
。
還有一個vars()
函式可以為您提供屬性及其值,但它不適用於所有情況。
包
到目前為止,您必須已經開始觀察組織程式的層次結構。變數通常進入函式內部。函式和全域性變數通常都在模組內部。如果你想組織模組怎麼辦?這就是包裝進入圖片的地方。
包只是模組的資料夾,帶有一個特殊__init__.py
檔案,向Python指示該資料夾是特殊的,因為它包含Python模組。
假設您想要建立一個名為'world'的包,包含'asia','africa'等子包,這些子包又包含'india','madagascar'等模組。
這是你如何構建資料夾:
- <some folder present in the sys.path>/
- world/
- __init__.py
- asia/
- __init__.py
- india/
- __init__.py
- foo.py
- africa/
- __init__.py
- madagascar/
- __init__.py
- bar.py
包只是分層組織模組的便利。您將在標準庫中看到許多此類例項。
摘要
就像函式是程式的可重用部分一樣,模組也是可重用的程式。包是組織模組的另一個層次結構。Python附帶的標準庫就是這樣一組包和模組的一個例子。
我們已經瞭解瞭如何使用這些模組並建立自己的模組。
接下來,我們將學習一些稱為資料結構的有趣概念。