模塊化編程
簡介
Python 有時候稱為膠水語言攘须,就是因?yàn)樗袕?qiáng)大的可擴(kuò)展性,這個擴(kuò)展性就是用模塊實(shí)現(xiàn)的捂敌。
模塊其實(shí)就是一個以 .py
結(jié)尾的 Python 文件惩坑,這個文件中可以包含變量、函數(shù)完域、類等软吐。
這個模塊可以包含實(shí)現(xiàn)了一個或者多個功能的代碼。
模塊可以在其他 Python 文件中使用吟税,可以通過網(wǎng)絡(luò)進(jìn)行傳播凹耙。
這樣的話,如果想在你的程序中實(shí)現(xiàn)某些功能肠仪,其實(shí)網(wǎng)絡(luò)的其他程序猿已經(jīng)給你寫好了肖抱,下載下來,安裝到自己的環(huán)境下异旧,就可以使用了意述。
模塊化編程
模塊化編程是指將大型,笨拙的編程任務(wù)分解為單獨(dú)的,更小的荤崇,更易于管理的子任務(wù)或模塊的過程拌屏。然后可以像構(gòu)建塊一樣拼湊單個模塊以創(chuàng)建更大的應(yīng)用程序。
在大型應(yīng)用程序中模塊化代碼有幾個優(yōu)點(diǎn):
- 簡單性:模塊通常只關(guān)注問題的一小部分术荤,而不是關(guān)注當(dāng)前的整個問題倚喂。如果您正在處理單個模塊,那么您的頭腦中要思考的將有一個較小的問題范圍瓣戚。這使得開發(fā)更容易端圈,更不容易出錯。
- 可維護(hù)性:模塊通常設(shè)計(jì)為能夠在不同的問題域之間實(shí)施邏輯邊界子库。如果以最小化相互依賴性的方式編寫模塊舱权,則對單個模塊的修改將對程序的其他部分產(chǎn)生影響的可能性降低。(您甚至可以在不了解該模塊之外的應(yīng)用程序的情況下對模塊進(jìn)行更改仑嗅。)這使得許多程序員團(tuán)隊(duì)在大型應(yīng)用程序上協(xié)同工作更加可行宴倍。
- 可重用性:單個模塊中定義的功能可以通過應(yīng)用程序的其他部分輕松地重用。這消除了重新創(chuàng)建重復(fù)代碼的需要仓技。
- 范圍:模塊通常定義一個單獨(dú)的命名空間啊楚,這有助于避免程序的不同區(qū)域中的變量名之間的沖突。
一浑彰、模塊分類
實(shí)現(xiàn)方式分類
實(shí)際上有兩種不同的方法可以在Python中定義模塊:
- 模塊可以用Python本身編寫。
- 模塊可以用C編寫并在運(yùn)行時動態(tài)加載拯辙,就像
re
(正則表達(dá)式)模塊一樣郭变。 - 一個內(nèi)置的模塊,本質(zhì)上已經(jīng)包含在了 Python 解釋器中,像
itertools
模塊
涯保。
以上情況下诉濒,模塊的內(nèi)容都以相同的方式訪問:使用import
語句
在這里,重點(diǎn)將主要放在用Python編寫的模塊上夕春。用Python編寫的模塊的妙處在于它們的構(gòu)建極其簡單未荒。您需要做的就是創(chuàng)建一個包含合法Python代碼的文件,然后為該文件命名并帶有 .py
擴(kuò)展名即可及志。
歸屬分類
模塊還可以分為
內(nèi)置模塊 片排,就是 python 解釋器中自帶的. 如:
os
re
itertools
第三方模塊, 這些模塊需要自己安裝速侈,就像是在 Linux 系統(tǒng)中安裝軟件一樣率寡。
自定義模塊, 這個就是自己編寫的模塊倚搬。
二冶共、模塊的安裝
安裝方法
1. pip3
工具安裝
例如下面的示例是安裝用于執(zhí)行遠(yuǎn)程主機(jī)命令的模塊 paramiko
注意: pip3 是 bash 環(huán)境下的命令
$ pip3 install paramiko
python2.x 使用
pip
python3.x 使用pip3
當(dāng)然這也不是固定的,比如你給pip3
定義了一個別名pip
2. 源碼安裝
源碼安裝就是,從網(wǎng)絡(luò)上下載沒有封裝的 python 文件的源碼捅僵,之后在本地執(zhí)行其源碼中的 setup.py
文件進(jìn)行安裝家卖。
模塊的源碼一般都有一個主目錄,主目錄中包含了一個到多個子目錄和文件庙楚。
但是主目錄下一定有一個 setup.py
的文件上荡,這個是源碼安裝的入口文件,就是需要執(zhí)行這個文件并且傳入一個 install
參數(shù)進(jìn)行源碼安裝醋奠。
示例:
a. 下載源碼包
wget https://files.pythonhosted.org/packages/4a/1b/9b40393630954b54a4182ca65a9cf80b41803108fcae435ffd6af57af5ae/redis-3.0.1.tar.gz
b. 解壓源碼包
tar -xf redis-3.0.1.tar.gz
- 進(jìn)入模塊源碼的主目錄榛臼,并安裝源碼包
上面表示安裝成功
三、自定義模塊
有的情況下窜司,是需要自己編寫一些模塊的沛善,這種就是自定義模塊了。
示例:
some_mod.py
x = 10
li = ['shark', 18]
def foo():
return 30
class Person():
def __init__(self, name, age):
self.name = name
self.age = age
四塞祈、模塊的使用
使用模塊需要先導(dǎo)入模塊名金刁。
模塊名就是把 .py
去掉后的文件名。比如 some_mod.py
的模塊名就是 some_mod
1. 導(dǎo)入模塊
import some_mod
2. 使用模塊中的對象
要想使用模塊中的變量名或者函數(shù)名等议薪,只需要使用 模塊名.變量名
的方式即可尤蛮。
例如,下面是使用的了 some_mod
模塊中的 foo
函數(shù)斯议。
import some_mod
some_mod.foo()
3. 更多模塊導(dǎo)入的方式
a. 從模塊中導(dǎo)入其中的一個對象
from some_mod import x
b. 從模塊中導(dǎo)入多個對象
from some_mod import x, foo
c. 從模塊中導(dǎo)入全部的對象, 不建議這么做, 應(yīng)該視使用模塊中的對象的情況而定
from some_mod import *
導(dǎo)入模塊時模塊的代碼會自動被執(zhí)行一次产捞,在一個程序中多次導(dǎo)入同一個模塊,此模塊的代碼僅會運(yùn)行一次哼御。
[root@kube-master py3]# cat some_mod.py
print("hello shark")
[root@kube-master py3]# cat t.py
import some_mod
import some_mod
[root@kube-master py3]# python t.py
hello shark
二坯临、包
包就是包含了一個 __init__.py
文件的文件夾,這個文件夾下可以有更多的目錄或文件恋昼。就是說看靠,包里可以用子包或單個 .py
的文件。
其實(shí)包也是模塊液肌,就是說包和單一的 .py
文件統(tǒng)稱為模塊挟炬。
包的目錄結(jié)構(gòu)
文件 __init__.py
__init__.py
文件,在 Python3.x 中可以沒有嗦哆,但是在 Python2.x 中必須有谤祖。
文件中可以有代碼,也可以是個空文件吝秕,但是文件名不能是其他的泊脐。
到導(dǎo)入包的時候,此文件假如存在烁峭,會以此文件去見包的名稱空間容客。
也就是說秕铛,導(dǎo)入如包的時候,只要在 __init__.py
文件中的名稱才可以生效缩挑。否則但两,即使是一個模塊在包目錄下面也不會被導(dǎo)入到內(nèi)存中,也就不會生效供置。
使用包
示例包目錄機(jī)構(gòu)
使用包也需要導(dǎo)入
a. 單獨(dú)導(dǎo)入包
import package # 注意這樣不會導(dǎo)入其下面的模塊和子包
b. 從包中導(dǎo)入下面的模塊
from package import t
c. 從包中導(dǎo)入下面的子包谨湘,注意這不會導(dǎo)入子包下面的任何模塊
from package import subpkg
d. 從包的子包中導(dǎo)入子包的模塊
from package.subpkg import som_mod
e. 從包或子包的模塊中導(dǎo)入具體的對象
from package.t import foo
from package.subpkg.som_mod import x
from package.t import x as y # 把 x 導(dǎo)入后起個別名 y
記住一點(diǎn):不論是導(dǎo)入包還是模塊,從左向右的順序來說芥丧,最后一個點(diǎn)兒的左邊一定是一個包名紧阔,而不能是一個模塊名
下面是錯誤的
import package.t.foo
from package.subpkg import som_mod.x
三模塊的內(nèi)置變量 __name__
每個 .py
文件都有一個變量名 __name__
, 這個變量名的值會根據(jù)這個文件的用途不同而隨之變化续担。
當(dāng)文件作為模塊被其他文件使用時擅耽,
__name__
的值是這個文件的模塊名當(dāng)文件作為腳本(就是作為可執(zhí)行文件)使用時,
__name__
的值是字符串類型的'__main__'
通常你會看到一些 Python 腳本中會有類似下面的代碼:
some_script.py
def foo():
pass
def func():
pass
def main():
foo()
func()
if __name__ == '__main__':
main()
使用這個腳本
python3 some_script.py
這樣執(zhí)行這個腳本的話物遇,其內(nèi)置的
__name__
變量的值就是字符串的'__main__'
乖仇。
這樣的話,if
的判斷添加就會達(dá)成询兴,從而其語句下面的代碼就會執(zhí)行乃沙,main()
函數(shù)就會被調(diào)用 。
模塊名包名的搜索路徑(擴(kuò)展)
這個就像是在 Linux 系統(tǒng)中诗舰,當(dāng)執(zhí)行一個命令時候警儒,系統(tǒng)會查找這個命令的二進(jìn)制文件一樣。Linux 系統(tǒng)是從環(huán)境變量 PATH
中查找眶根。
查找順序
當(dāng)你導(dǎo)入模塊或者包的時候, 查找模塊或包的順序:
系統(tǒng)會從內(nèi)存中查找冷蚂,看是否之前已經(jīng)導(dǎo)入過此模塊。
假如第一次導(dǎo)入汛闸,內(nèi)存中就不會存在,這時再從當(dāng)前目錄下查找艺骂。
最再從
sys.path
輸出的值中的路徑里查找模塊名或者包名诸老。
都找不到,就會報錯钳恕,并且整個程序會退出
image
import sys
print(sys.path)
sys.path
輸出的值是一個 Python 的列表别伏,這個列表我們可以對其修改的。
比如我們可以把某個文件的路徑添加到此列表中忧额,通常會這么做厘肮。
run.py
import os,sys
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, BASE_DIR)