解耦總的一句話來說,減少依賴,抽象業務和邏輯,讓各個功能實現獨立。
直觀理解“解耦”,就是我可以替換某個模塊,對原來系統的功能不造成影響。是兩個東西原來互相影響,現在讓他們獨立發展;核心思想還是最小職責,每個地方都只做一件事情;只要一個地方負責了多項事情,就存在解耦的可能。在系統每個層次都可以體現解耦的思想,比如在架構層面把存儲和業務邏輯解耦,把動態頁面和靜態頁面解耦;在模塊層面把業務模塊和統計模塊解耦;在代碼層面把多個功能解耦等等。
低耦合,高內聚---模塊之間低耦合,模塊內部高內聚。一個系統有多個模塊組成,在划分模塊時,要把功能關系緊密的放到一個模塊中(高內聚),功能關系遠的放到其它模塊中。模塊之間的聯系越少越好,接口越簡單越好(低耦合,細線通信)。
二、模塊
概念
在計算機程序的開發過程中,隨着程序代碼越寫越多,在一個文件里代碼就會越來越長,越來越不容易維護。為了編寫可維護的代碼,我們把很多函數分組,分別放到不同的文件里,這樣,每個文件包含的代碼就相對較少,很多編程語言都采用這種組織代碼的方式。在Python中,一個.py文件就稱之為一個模塊(Module)。
使用模塊的好處
最大的好處是大大提高了代碼的可維護性;其次,編寫代碼不必從零開始。當一個模塊編寫完畢,就可以被其他地方引用。
模塊的種類
-
python標准庫
-
第三方模塊
-
應用程序自定義模塊:自定義模塊時要注意命名,不能和Python自帶的模塊名稱沖突。
模塊的導入方法
import
import module1
import 模塊名,一般是導入python的內置模塊
import as
import multiprocessing as mul
在之后的代碼中就可以直接用mul.方法名了,不用寫長長的multiprocessing.方法名
from…import 語句
from modname import name1[, name2[, ... nameN]]
from 模塊 import 方法名 ,這個聲明不會把整個modulename模塊導入到當前的命名空間中,只會將它里面的name1或name2單個方法引入到執行文件里
from…import* 語句
from modname import *
這提供了一個簡單的方法來導入一個模塊中的所有項目。然而這種聲明不該被過多地使用。大多數情況, Python程序員不使用這種方法,因為引入的其它來源的命名,很可能覆蓋了已有的定義。
注意:
模塊一旦被導入,即相當於執行了一個.py文件(導入模塊所在的文件)里的代碼
import的工作機制
import語句導入指定的模塊時會執行3個步驟
1.找到模塊文件:在模塊搜索路徑下搜索模塊文件
程序的主目錄
PYTHONPATH目錄
標准鏈接庫目錄
2.編譯成字節碼:文件導入時會編譯,因此,頂層文件的.pyc字節碼文件在內部使用后會被丟棄,只有被導入的文件才會留下.pyc文件
3.執行模塊的代碼來創建其所定義的對象:模塊文件中的所有語句從頭至尾依次執行,而此步驟中任何對變量名的賦值運算,都會產生所得到的模塊文件的屬性(所以自定義函數不要和模塊中的名稱重合)
不同目錄類型的模塊文件導入
1、與執行文件同目錄模塊導入
文件目錄結構如下
test.py是執行文件,想調用manage.py模塊
可以直接用
import manage
或者
from manage import *
2、不同文件目錄的模塊導入
M2
├── bin
│ ├── __init__.py
│ └── start.py [程序入口]
├── conf
│ ├── __init__.py
│ └── settings.py
├── core
│ ├── __init__.py
│ ├── accounts.py
│ ├── db_handler.py
│ ├── logger.py
│ ├── main.py
│ └── transaction.py
├── test.py
start.py是執行文件,不同目錄下面入口程序得目錄加載到sys.path即環境變量中,就可以跨模塊調用了
在settings.py 里加入
import sys,os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR)
這里os.path.abspath(__file__)獲取返回settings.py規范化的絕對路徑(包含文件),
os.path.dirname(os.path.abspath(__file__))
獲取當前運行腳本的絕對路徑(去掉最后一個文件),
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
獲取當前運行腳本的絕對路徑(去掉最后一個路徑)
注意的一點是:直接用路徑添加sys.path.append()添加目錄時注意是在windows還是在Linux下,windows下需要‘\’否則會出錯。
此時的模塊搜索的主目錄是 */M2/,即在M2文件夾下搜索
需求1:
mian.py想要引用accounts模塊下的函數需要
from core import accounts
也可以這樣寫
from . import accounts
從當前目錄導入模塊(但是這里添加的搜索主目錄是上級目錄,即這個例子的M2文件夾)
需求2:
main.py 想要引用settings模塊需要
from conf import settings
需求3:
test.py想要引用logger.py模塊需要
from core import logger
from ..proj import hello (待補充)
注意:python使用. .. 相對導入模塊要滿足兩個條件:
1.文件夾中必須有__init__.py文件
,該文件可以為空,但必須要有
2.不能作為頂層模塊來執行該文件夾中得py文件(即不能作為主函數得入口) 意思:..后不能到主函數入口得目錄下
例子
index.py位置為D:\test_package\a\b\c\index.py
文件目錄樹
D:. │ test.py │ __init__.py │ ├─a │ │ __init__.py │ │ │ ├─b │ │ └─c │ │ index.py │ │ __init__.py │ │ │ └─__pycache__ │ __init__.cpython-36.pyc │ └─__pycache__
test.py想要導入index模塊需要
from a.b.c import index
內置變量: __file__
表示當前的文件名
os.path.abspath(path) :返回path的絕對路徑
os.path.dirname(path) :返回path的目錄(去掉最后一級目錄或文件)
例子
index.py文件位置為D:\python\exercise\test_package\b\index.py
在index.py寫入
import os BASE_DIR0 =os.path.abspath(__file__) BASE_DIR1 = os.path.dirname(os.path.abspath(__file__)) #去掉最后一個文件,返回路徑 BASE_DIR2 = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#去掉最后一級目錄返回路徑 print(BASE_DIR0) print(BASE_DIR1) print(BASE_DIR2) print("這里是index")
運行輸出結果
D:\python\exercise\test_package\b\index.py D:\python\exercise\test_package\b D:\python\exercise\test_package 這里是index
if __name__
== '__main__
':
一個模塊文件可以直接執行或被導入
每個模塊都有一個名為__name__
的內置變量,此變量值會根據調用此模塊的方式發生變化:\1. 如果此文件被作為模塊導入,則__name__
的值為模塊名稱\2. 如果此文件被直接執行,則__name__
的值為“__main__
”
我們在創建模塊時,在尾部添加如下代碼進行模塊的自我測試if __name__
== '__main__
':
...
如果模塊被導入,則 if 后的語句就不會執行
安裝第三方模塊
安裝第三方模塊有兩種方式:
1.通過包管理工具pip完成的
即pip install 模塊名或者pip3 install 模塊名
注意:Mac或Linux上有可能並存Python 3.x和Python 2.x,因此對應的pip命令是pip3
2.下載源碼=> 解壓源碼=> 進入目錄
源碼格式大概都是 zip 、 tar.zip、 tar.bz2格式的壓縮包。解壓這些包,進入解壓好的文件夾,通常會看見一個 setup.py 的文件。打開命令行,進入該文件夾。
python setup.py install
三、包
包一個文件夾下有多個.py文件,加上__init__空
文件,這個文件夾就是一個包了
包是一個有層次的文件目錄結構,它定義了一個由模塊和子包組成的Python應用執行環境
基於包,Python在執行模塊導入時可以指定模塊的導入路徑 import pack1.pack2.mod1
每個包內都必須有__init__.py
文件,可包含python代碼,但通常為空,僅用於扮演包初始化、替目錄產生模塊命名空間以及使用目錄導入時實現from*行為的角色