目錄
1. 子產品化(module)程式設計理念
1.1 子產品和包概念的進化史
1.2 标準庫子產品(standard library)
1.3 為什麼需要子產品化程式設計
1.4 子產品化程式設計的流程
1.6 子產品的建立和測試代碼
1.7 子產品文檔字元串和API 設計
2. 子產品的導入
2.1 import 語句導入
2.2 from…import 導入
2.3 import 語句和from...import 語句的差別
2.4 __import__()動态導入
2.5 子產品的加載問題
3. 包package 的使用
3.1 包(package)的概念和結構
3.2 pycharm 中建立包
3.3 導入包操作和本質
3.4 用*導入包
3.5 包内引用
3.6 sys.path 和子產品搜尋路徑
4. 子產品釋出和安裝
4.1 子產品的本地釋出
4.2 本地安裝子產品
4.3 上傳子產品到PyPI
1. 子產品化(module)程式設計理念
1.1 子產品和包概念的進化史
“量變引起質變”是哲學中一個重要的理論。量變為什麼會引起質變呢?本質上了解,随着數量的增加,管理方式會發生本質的變化;舊的管理方式完全不适合,必須采用新的管理方式。
程式越來越複雜,語句多了,怎麼管理?很自然的,我們會将實作同一個功能的語句封裝到函數中,統一管理和調用,于是函數誕生了。
程式更加複雜,函數和變量多了,怎麼管理?同樣的思路,“物以類聚”,我們将同一類型對象的“資料和行為”,也就是“變量和函數”,放到一起統一管理和調用,于是“類和對象”誕生了。
程式繼續複雜,函數和類更加多了,怎麼辦?好,我們将實作類似功能的函數和類統統放到一個子產品中,于是“子產品”誕生了。
程式還要複雜,子產品多了,怎麼辦? 于是,我們将實作類似功能的子產品放到一起,于是“包”就誕生了。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI2EzX4xSZz91ZsAzNfRHLGZkRGZkRfJ3bs92YsAjMfVmepNHLtlWN10ScaZTOXFWNnlnY1A1QiVTQClGVF5UMR9Fd4VGdsATNfd3bkFGazxycykFaKdkYzZUbapXNXlleSdVY2pESa9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL4QDO2IDOyAjMzETOwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
1. Python 程式由子產品組成。一個子產品對應python 源檔案,一般字尾名是:.py。
2. 子產品由語句組成。運作Python 程式時,按照子產品中語句的順序依次執行。
3. 語句是Python 程式的構造單元,用于建立對象、變量指派、調用函數、控制語句等。
1.2 标準庫子產品(standard library)
與函數類似,子產品也分為标準庫子產品和使用者自定義子產品。
Python 标準庫提供了作業系統功能、網絡通信、文本處理、檔案處理、數學運算等基本的功能。比如:random(随機數)、math(數學運算)、time(時間處理)、file(檔案處理)、os(和作業系統互動)、sys(和解釋器互動)等。
另外,Python 還提供了海量的第三方子產品,使用方式和标準庫類似。功能覆寫了我們能想象到的所有領域,比如:科學計算、WEB 開發、大資料、人工智能、圖形系統等。
1.3 為什麼需要子產品化程式設計
子產品(module)對應于Python 源代碼檔案(.py 檔案)。子產品中可以定義變量、函數、類、普通語句。這樣,我們可以将一個Python 程式分解成多個子產品,便于後期的重複應用。
子產品化程式設計(Modular Programming)将一個任務分解成多個子產品。每個子產品就像一個積木一樣,便于後期的反複使用、反複搭建。
子產品化程式設計有如下幾個重要優勢:
1. 便于将一個任務分解成多個子產品,實作團隊協同開發,完成大規模程式
2. 實作代碼複用。一個子產品實作後,可以被反複調用。
3. 可維護性增強。
1.4 子產品化程式設計的流程
子產品化程式設計的一般流程:
1. 設計API,進行功能描述。
2. 編碼實作API 中描述的功能。
3. 在子產品中編寫測試代碼,并消除全局代碼。
4. 使用私有函數實作不被外部用戶端調用的子產品函數。
"""
用于計算公司員工的薪資
"""
company = "北京尚學堂"
def yearSalary(monthSalary):
#計算年薪
"""根據傳入的月薪的值,計算出年薪:monthsalary*12"""
return monthSalary*12
def daySalary(monthSalary):
"""根據傳入的月薪值,計算出1天的薪資。一個月按照22.5天計算(國家規定的工作日)"""
return monthSalary/22.5
if __name__ == "__main__":
print(yearSalary(5000))
1.6 子產品的建立和測試代碼
每個子產品都有一個名稱,通過特殊變量__name__可以擷取子產品的名稱。在正常情況下,子產品名字對應源檔案名。僅有一個例外,就是當一個子產品被作為程式入口時(主程式、互動式提示符下),它的__name__的值為“__main__”。我們可以根據這個特點,将子產品源代碼檔案中的測試代碼進行獨立的處理。
1.7 子產品文檔字元串和API 設計
我們可以在子產品的第一行增加一個文檔字元串,用于描述子產品的相關功能。然後,通過__doc__可以獲得文檔字元串的内容。
2. 子產品的導入
子產品化設計的好處之一就是“代碼複用性高”。寫好的子產品可以被反複調用,重複使用。子產品的導入就是“在本子產品中使用其他子產品”。
2.1 import 語句導入
import 語句的基本文法格式如下:
import 子產品名 #導入一個子產品
import 子產品1,子產品2… #導入多個子產品
import 子產品名as 子產品别名 #導入子產品并使用新名字
import 加載的子產品分為四個通用類别:
a.使用python 編寫的代碼(.py 檔案);
b.已被編譯為共享庫或DLL 的C 或C++擴充;
c.包好一組子產品的包
d.使用C 編寫并連結到python 解釋器的内置子產品;
我們一般通過import 語句實作子產品的導入和使用,import 本質上是使用了内置函數__import__()。
當我們通過import 導入一個子產品時,python 解釋器進行執行,最終會生成一個對象,這個對象就代表了被加載的子產品。
2.2 from…import 導入
Python 中可以使用from…import 導入子產品中的成員。基本文法格式如下:
from 子產品名import 成員1,成員2,…
如果希望導入一個子產品中的所有成員,則可以采用如下方式:
from 子產品名import *
【注】盡量避免“from 子產品名import *”這種寫法。* 它表示導入子產品中所有的不是以下劃線(_)開頭的名字都導入到目前位置。但你不知道你導入什麼名字,很有可能會覆寫掉你之前已經定義的名字。而且可讀性極其的差。
2.3 import 語句和from...import 語句的差別
import 導入的是子產品。from...import 導入的是子產品中的一個函數/一個類。
如果進行類比的話,import 導入的是“檔案”,我們要使用該“檔案”下的内容,必須前面加“檔案名稱”。from...import 導入的是檔案下的“内容”,我們直接使用這些“内容”即可,前面再也不需要加“檔案名稱”了。
2.4 __import__()動态導入
import 語句本質上就是調用内置函數__import__(),我們可以通過它實作動态導入。給
__import__()動态傳遞不同的的參數值,就能導入不同的子產品。
注意:一般不建議我們自行使用__import__()導入,其行為在python2 和python3 中
有差異,會導緻意外錯誤。如果需要動态導入可以使用importlib 子產品。
import importlib
a = importlib.import_module("math")
print(a.pi)
2.5 子產品的加載問題
當導入一個子產品時, 子產品中的代碼都會被執行。不過,如果再次導入這個子產品,則不會再次執行。
Python 的設計者為什麼這麼設計?因為,導入子產品更多的時候需要的是定義子產品中的變量、函數、對象等。這些并不需要反複定義和執行。“ 隻導入一次import-only-once”就成了一種優化。
一個子產品無論導入多少次,這個子產品在整個解釋器程序内有且僅有一個執行個體對象。
重新加載:有時候我們确實需要重新加載一個子產品,這時候可以使用:importlib.reload()方法
import test02
import test02
print("####")
import importlib
importlib.reload(test02)
3. 包package 的使用
3.1 包(package)的概念和結構
當一個項目中有很多個子產品時,需要再進行組織。我們将功能類似的子產品放到一起,形成了“包”。本質上,“包”就是一個必須有__init__.py 的檔案夾。典型結構如下:
包下面可以包含“子產品(module)”,也可以再包含“子包(subpackage)”。就像檔案夾下面可以有檔案,也可以有子檔案夾一樣。
上圖中,a 是上層的包,下面有一個子包:aa。可以看到每個包裡面都有__init__.py 檔案。
3.2 pycharm 中建立包
在pycharm 開發環境中建立包,非常簡單。在要建立包的地方單擊右鍵:New-->Python package 即可。pycharm 會自動幫助我們生成帶有__init__.py 檔案的包。
3.3 導入包操作和本質
上一節中的包結構,我們需要導入module_AA.py。方式如下:
1. import a.aa.module_AA
在使用時,必須加完整名稱來引用,比如:a.aa.module_AA.fun_AA()
2. from a.aa import module_AA
在使用時,直接可以使用子產品名。比如:module_AA.fun_AA()
3. from a.aa.module_AA import fun_AA 直接導入函數
在使用時,直接可以使用函數名。比如:fun_AA()
【注】
1. from package import item 這種文法中,item 可以是包、子產品,也可以是函數、類、變量。
2. import item1.item2 這種文法中,item 必須是包或子產品,不能是其他。
導入包的本質其實是“導入了包的__init__.py”檔案。也就是說,”import pack1”意味着執行了包pack1 下面的__init__.py 檔案。這樣,可以在__init__.py 中批量導入我們需要的子產品,而不再需要一個個導入。
__init__.py 的三個核心作用:
1. 作為包的辨別,不能删除。
2. 用來實作模糊導入
3. 導入包實質是執行__init__.py 檔案,可以在__init__.py 檔案中做這個包的初始化、以及
需要統一執行代碼、批量導入。
3.4 用*導入包
import * 這樣的語句理論上是希望檔案系統找出包中所有的子子產品,然後導入它們。這可能會花長時間等。Python 解決方案是提供一個明确的包索引。
這個索引由__init__.py 定義__all__ 變量,該變量為一清單,如上例a 包下的__init__.py 中,可定義__all__ = ["module_A","module_A2"]
這意味着, from sound.effects import * 會從對應的包中導入以上兩個子子產品;
【注】盡管提供import * 的方法,仍不建議在生産代碼中使用這種寫法。
3.5 包内引用
如果是子包内的引用,可以按相對位置引入子子產品以aa 包下的module_AA 中導入a包下内容為例:
from .. import module_A #..表示上級目錄.表示同級目錄
from . import module_A2 #.表示同級目錄
3.6 sys.path 和子產品搜尋路徑
當我們導入某個子產品檔案時, Python 解釋器去哪裡找這個檔案呢?隻有找到這個檔案才能讀取、裝載運作該子產品檔案。它一般按照如下路徑尋找子產品檔案(按照順序尋找,找到即停不繼續往下尋找):
1. 内置子產品
2. 目前目錄
3. 程式的主目錄
4. pythonpath 目錄(如果已經設定了pythonpath 環境變量)
5. 标準連結庫目錄
6. 第三方庫目錄(site-packages 目錄)
7. .pth 檔案的内容(如果存在的話)
8. sys.path.append()臨時添加的目錄
· pythonpath 環境變量的設定
windows 系統中通過如下操作添加和設定pythonpath 環境變量。
· .pth 檔案的寫法
我們可以在site-packages 目錄下添加.pth 檔案。并在檔案中增加内容:
#一行一個目錄
g:\a
g:\b
g:\c
【注】
1. 需確定g:\a,g:\b,g:\c 對應的目錄真實存在。
2. 在windows 系統中建立.pth 檔案,由于沒有檔案名不能直接建立。需要輸入“.pth.”才能正常建立.pth 檔案。
4. 子產品釋出和安裝
4.1 子產品的本地釋出
當我們完成了某個子產品開發後,可以将他對外釋出,其他開發者也可以以“第三方擴充庫”的方式使用我們的子產品。我們按照如下步驟即可實作子產品的釋出:
1.為子產品檔案建立如下結構的檔案夾(一般,檔案夾的名字和子產品的名字一樣):
2.在檔案夾中建立一個名為『setup.py』的檔案,内容如下:
2.在檔案夾中建立一個名為『setup.py』的檔案,内容如下:
from distutils.core import setup
setup(
name='baizhanMath2', # 對外我們子產品的名字
version='1.0', # 版本号
description='這是第一個對外釋出的子產品,測試哦', #描述
author='gaoqi', # 作者
author_email='[email protected]',
py_modules=['baizhanMath2.demo1','baizhanMath2.demo2'] # 要釋出的子產品
)
3. 建構一個釋出檔案。通過終端,cd 到子產品檔案夾c 下面,再鍵入指令:
python setup.py sdist
執行完畢後,目錄結構變為:
4.2 本地安裝子產品
将釋出安裝到你的本地計算機上。仍在cmd 指令行模式下操作,進setup.py 所在目錄,鍵入指令:python setup.py install
安裝成功後,我們進入python 目錄/Lib/site-packages 目錄(第三方子產品都安裝的這裡,python 解釋器執行時也會搜尋這個路徑):
安裝成功後,直接使用import 導入即可:import baizhanMath2.demo1
4.3 上傳子產品到PyPI
将自己開發好的子產品上傳到PyPI 網站上,将成為公開的資源,可以讓全球使用者自由使用。按照如下步驟做,很容易就實作上傳子產品操作。
·注冊PyPI 網站
注冊PyPI 網站:http://pypi.python.org
【注意】會發送一封郵件到你的郵箱。請點選驗證後繼續下面的步驟。
·建立使用者資訊檔案.pypirc
·方式1: 使用指令(适用Linux)
輸入并執行後python setup.py register ,然後輸入使用者名和密碼,即可。
·方式2:使用檔案(适用windows,Linux)
在使用者的家目錄裡建立一個檔案名為.pypirc, 内容為:
[distutils]
index-servers=pypi
[pypi]
repository = https://upload.pypi.org/legacy/
username = 賬戶名
password = 你自己的密碼
【注】
Linux 的家目錄: ~/.pypirc
Windows 的家目錄是: c:/user/使用者名
在windows 下直接建立不包含檔案名的檔案會失敗,是以建立時檔案名為“.pypirc.”,前後都有兩個點即可。
·上傳并遠端釋出
進入setup.py 檔案所在目錄,使用指令“python setup.py sdist upload”,即可以
将子產品代碼上傳并釋出:
·管理你的子產品
我們登入pypi 官網,可以看到:
如果你的子產品已經上傳成功,那麼當你登入PyPI 網站後應該能在右側導航欄看到管理
入口。