- 爲了編寫可維護的代碼,我們把函數分組,分別放到不同的文件夾裏,在python中,一個.py文件就稱之爲一個模塊(Module)
- 使用模塊有什麼好處呢:一是:大大提高了代碼的可維護性,當一個模塊編寫完成以後,就可以在其他地方引用這些模塊;二是:使用模塊避免函數名和變量名衝突,相同名字的函數和變量可以存在不同的模塊中,但也要注意,不要與內置函數名衝突;
- 爲了避免不同的人編寫的模塊名相同,python又引入了按目錄來組織模塊的方法,成爲包(Package);
- 舉個例子,一個
abc.py
的文件就是一個名字叫abc
的模塊,一個xyz.py
的文件就是一個名字叫xyz
的模塊,現在假設我們的這兩個模塊的名字與其他模塊衝突了,我們可以通過包來組織模塊,方法就是選擇一個頂層包名,比如mycompany
,按照如下目錄存放:
- 引入了包以後,只要頂層的包名不與其他人衝突,把所有模塊就不會與其他人衝突,現在
abc.py
模塊的名字就變成了mycompany.abc
,類似的,xyz.py
的模塊名變成了mycompany.xyz
;請注意,每一個包目錄下面都有一個__int__.py
的文件,這個文件時必須存在的,否則python就會這個目錄變成一個普通的目錄,而不是一個包,__int__.py
可以是一個空文件,也可以有代碼,因爲,__int__.py
本身就是一個模塊,而他的模塊名就是mycompany
; - 類似的可以有多級目錄,組成多層級的包結構:
- 文件
www.py
模塊名就是mycompany.web.www
,兩個文件utils.py
的模塊名分別是mycompany.utils
和mycompany.web.utils
; - mycompany.web也是一個模塊,該模塊對應的是
__int__.py
文件; - 自己創建模塊時要注意命名,不能和Python自帶的模塊名稱衝突。例如,系統自帶了
sys
模塊,自己的模塊就不可命名爲sys.py
,否則將無法導入系統自帶的sys
模塊。
1. 使用模塊
1.1 使用模塊
- python內置了很多有用的模塊,安裝完畢即可使用,下面以內建的
sys
模塊爲例,編寫一個hello
的模塊:
#!/user/bin/env python3 本行註釋可以讓此`hello.py`文件直接在linux/mac/unix上運行
# -*- coding: utf-8 -*- 本行註釋表示.py文件使用標準UTF-8編碼
' a test module ' # 任何代碼模塊的第一個字符串都被視爲模塊的文檔註釋
__author__ = 'Michael Zhao' # 使用__author__變量把作者寫進去,當你公開源碼的時候,別人就能看見你的名字
# 以上爲python模塊的標準文件模板,後面是真正代碼部分
import sys # 導入sys模塊,我們就有了變量sys指向sys模塊,利用sys這個變量就可以訪問sys模塊的所有功能
def test():
args = sys.argv
if len(args)==1:
print('Hello, world!')
elif len(args)==2:
print('Hello, %s!' % args[1])
else:
print('Too many arguments!')
if __name__ == '__main__':
test()
-
sys
模塊有一個argv
變量,用list存儲了命令行的所有參數,argv
至少有一個元素,因爲第一個參數永遠是該.py文件的名稱,如:運行python3 hello.py
獲得的sys.argv
就是['hello.py']
;運行python3 hello.py Micheal
獲得的sys.argv
就是['hello.py', 'Michael']
。 -
最後注意到最後兩行代碼:當我們在命令行運行
hello
模塊文件時,python解釋器把一個特殊變量__name__
置爲__main__
,而如果在其他地方導入該hello
模塊時,if
判斷失敗,因此,這種if
測試可以讓一個模塊通過命令行運行時執行一些額外的代碼,最常見的就是運行測試。 -
當我們用命令行運行
hello.py
時:
$ python hello.py
Hello, world!
$ python hello.py Michael
Hello, Michael!
- 當我們啓動python交互式環境,再導入
hello
模塊:
(base) E:\4_Programe\1_Python\3_Code\1_LiaoDaDa>python
Python 3.7.0 (default, Jun 28 2018, 08:04:48) [MSC v.1912 64 bit (AMD64)] :: Anaconda, Inc. on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import hello # 導入時,沒有打印Hello, world!,因爲沒有執行test()函數
>>> hello.test() # 調用hello.test()時,纔打印Hello, world!
Hello, world!
1.2 作用域
- 在一個模塊中,會定義很多變量和函數,有些我們只是希望自己使用,並不像別人共用,所以在python中是通過
_
前綴來實現的:正常的函數和變量名時公開的,可以被直接引用,比如:abc
,x123
,PI
等; - 類似於
__xxx__
這樣的變量是特殊變量,可以被直接引用,但是有特殊用途,我們自己的變量一般不要用這種變量名; - 類似於
_xxx
和__xxx
這樣的函數或變量就是非公開的(private),不應該被直接引用,如:_abc
,__abc
等;不應該被直接引用不代表不能被直接引用,是因爲從編程習慣上不應該引用private函數或變量; - private函數或變量不應該被被人引用,那他有什麼用呢?請看:
def _private_1(name):
return 'Hello, %s' % name
def _private_2(name):
return 'Hi, %s' % name
def greeting(name):
if len(name) > 3:
return _private_1(name)
else:
return _private_2(name)
- 我們在模塊裏公開
greeting()
函數,而把內部邏輯用private函數隱藏起來了,這樣,調用greeting()
函數不用關心內部的private函數細節,這也是一種非常有用的代碼封裝和抽象的方法,即:外部不需要引用的函數全部定義成private,只有外部需要引用的函數才定義爲public。
2. 安裝第三方模塊
- 在Python中,安裝第三方模塊是通過包管理工具pip完成的
- 在Linux/Mac中安裝pip這個步驟可以跳過,若在win中,確定安裝python的時候,勾選了
pip
和Add python.exe to Path
,在命令提示符窗口下嘗試運行pip
,如果沒有報錯,則正常 - 安裝第三方庫Pillow的命令是:
pip install Pillow # 耐心等待下載安裝即可
2.1 安裝常用模塊
- 安裝Anaconda,內置了很多第三方庫;
2.2 模塊搜索路徑
- 當我們試圖加載一個模塊時,Python會在指定的路徑下搜索對應的.py文件,如果找不到,就會報錯;
>>> import mymodule
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'mymodule'
- 默認情況下,Python解釋器會搜索當前目錄,所有已安裝的內置模塊和第三方模塊,搜索路徑放在
sys
模塊的path
變量中:
>>> import sys
>>> sys.path
['', 'E:\\1_Install_Total\\8_Anaconda\\python37.zip', 'E:\\1_Install_Total\\8_Anaconda\\DLLs', 'E:\\1_Install_Total\\8_Anaconda\\lib', 'E:\\1_Install_Total\\8_Anaconda', 'E:\\1_Install_Total\\8_Anaconda\\lib\\site-packages', 'E:\\1_Install_Total\\8_Anaconda\\lib\\site-packages\\win32', 'E:\\1_Install_Total\\8_Anaconda\\lib\\site-packages\\win32\\lib', 'E:\\1_Install_Total\\8_Anaconda\\lib\\site-packages\\Pythonwin']
- 如果要自己添加路徑,有兩種方法:
- 直接修改
sys.path
,添加要搜索的目錄:
>>> import sys
>>> sys.path.append('/User/michael/my_py_scripts')
# 這種方法是在運行時修改,運行結束以後失效
- 設置環境變量
PYTHONPATH
,該環境變量的內容會被自動添加到模塊搜索路徑中。設置方式與設置Path環境變量類似。注意只需要添加你自己的搜索路徑,Python自己本身的搜索路徑不受影響。