[TOC]
參考鏈接
* [銀角大王講裝飾器](http://www.cnblogs.com/wupeiqi/articles/4980620.html#undefined)
* [Python 迭代器/生成器/裝飾器](https://www.jianshu.com/p/c77b71a690db)
## **引子**
### 開放封閉原則
在一個已經正常運行的項目中,對項目功能的增加,需要遵循開放封閉原則.
簡單來說,它規定已經實現的功能代碼不允許被修改,但可以被擴展,即:
* 封閉:已實現的功能代碼塊不應該被修改
* 開放:對現有功能的擴展開放
### 不改變調用原則
對已經功能的增改,不能修改原模塊(函數)的調用方式,因為一個模塊(函數)可能已經在N個地方使用了,如果改變了調用方式,就需要修改N個地方
## **裝飾器**
裝飾器的作用就是**在不修改原函數的情況下添加新功能**,相當于高階函數(將函數作為參數傳入)和嵌套函數的結合.
### 裝飾器基本格式:
```python
def 裝飾器函數(傳入的函數):
def 執行的嵌套函數(傳入函數的參數):
裝飾器語句
...
return 傳入的函數(傳入函數的參數)
...
裝飾器語句
return 返回的嵌套函數
@裝飾器函數
def 原函數
原函數模塊...
```
### 無參數的裝飾器
```python
def w1(func):
def inner():
# 驗證1
# 驗證2
# 驗證3
return func()
return inner
@w1
def f1():
print 'f1'
```
### 參數格式已知的裝飾器
```
def w1(func):
def inner(arg1,arg2,arg3):
# 驗證1
# 驗證2
# 驗證3
return func(arg1,arg2,arg3)
return inner
@w1
def f1(arg1,arg2,arg3):
print 'f1'
```
### 參數格式未知的裝飾器
```
def w1(func):
def inner(*args,**kwargs):
# 驗證1
# 驗證2
# 驗證3
return func(*args,**kwargs)
return inner
@w1
def f1(arg1,arg2,arg3):
print 'f1'
```
### 多個裝飾器裝飾一個函數
```
def w1(func):
def inner(*args,**kwargs):
# 驗證1
# 驗證2
# 驗證3
return func(*args,**kwargs)
return inner
def w2(func):
def inner(*args,**kwargs):
# 驗證1
# 驗證2
# 驗證3
return func(*args,**kwargs)
return inner
@w1
@w2
def f1(arg1,arg2,arg3):
print 'f1'
```
## 裝飾器流程詳解
### 1.簡單代碼
以上面的無參數的裝飾器來做解釋
```
def w1(func):
def inner():
# 驗證代碼1
return func()
return inner
@w1
def f1():
print 'f1'
```
### 2.代碼執行步驟
當寫完這段代碼后(函數未被執行、未被執行、未被執行),python解釋器就會從上到下解釋代碼,步驟如下:
1. `def w1(func): ` ==>將w1函數加載到內存
2. `@w1
`
沒錯,從表面上看解釋器僅僅會解釋這兩句代碼,因為函數在沒有被調用之前其內部代碼不會被執行。
從表面上看解釋器著實會執行這兩句,但是 @w1 這一句代碼里卻有大文章,@函數名 是python的一種語法糖。
### 3.將原函數作為參數傳給新函數
如上例@w1內部會執行一下操作:
**執行w1函數**,并將 @w1 下面的 函數 作為w1函數的參數,即:@w1 等價于 w1(f1)
所以,內部就會去執行:
```
def inner:
#驗證
return f1() # func是參數,此時 func 等于 f1
return inner # 返回的 inner,inner代表的是函數,非執行函數
```
>其實就是將原來的 f1 函數塞進另外一個函數中
### 4.新函數執行完畢后再將原函數return返回
將執行完的 w1 函數**返回值賦值**給@w1下面的函數的函數名
```
w1函數的返回值是:
def inner:
#驗證
return 原來f1() # 此處的 f1 表示原來的f1函數
然后,將此返回值再重新賦值給 f1,即:
新f1 = def inner:
#驗證
return 原來f1()
```
>所以,以后業務部門想要執行 f1 函數時,就會執行 新f1 函數,在 新f1 函數內部先執行驗證,再執行原來的f1函數,然后將 原來f1 函數的返回值 返回給了業務調用者。
如此一來, 即執行了驗證的功能,又執行了原來f1函數的內容,并將原f1函數返回值 返回給業務調用著
- 基礎部分
- 基礎知識
- 變量
- 數據類型
- 數字與布爾詳解
- 列表詳解list
- 字符串詳解str
- 元組詳解tup
- 字典詳解dict
- 集合詳解set
- 運算符
- 流程控制與循環
- 字符編碼
- 編的小程序
- 三級菜單
- 斐波那契數列
- 漢諾塔
- 文件操作
- 函數相關
- 函數基礎知識
- 函數進階知識
- lambda與map-filter-reduce
- 裝飾器知識
- 生成器和迭代器
- 琢磨的小技巧
- 通過operator函數將字符串轉換回運算符
- 目錄規范
- 異常處理
- 常用模塊
- 模塊和包相關概念
- 絕對導入&相對導入
- pip使用第三方源
- time&datetime模塊
- random隨機數模塊
- os 系統交互模塊
- sys系統模塊
- shutil復制&打包模塊
- json&pickle&shelve模塊
- xml序列化模塊
- configparser配置模塊
- hashlib哈希模塊
- subprocess命令模塊
- 日志logging模塊基礎
- 日志logging模塊進階
- 日志重復輸出問題
- re正則表達式模塊
- struct字節處理模塊
- abc抽象類與多態模塊
- requests與urllib網絡訪問模塊
- 參數控制模塊1-optparse-過時
- 參數控制模塊2-argparse
- pymysql數據庫模塊
- requests網絡請求模塊
- 面向對象
- 面向對象相關概念
- 類與對象基礎操作
- 繼承-派生和組合
- 抽象類與接口
- 多態與鴨子類型
- 封裝-隱藏與擴展性
- 綁定方法與非綁定方法
- 反射-字符串映射屬性
- 類相關內置方法
- 元類自定義及單例模式
- 面向對象的軟件開發
- 網絡-并發編程
- 網絡編程SOCKET
- socket簡介和入門
- socket代碼實例
- 粘包及粘包解決辦法
- 基于UDP協議的socket
- 文件傳輸程序實戰
- socketserver并發模塊
- 多進程multiprocessing模塊
- 進程理論知識
- 多進程與守護進程
- 鎖-信號量-事件
- 隊列與生產消費模型
- 進程池Pool
- 多線程threading模塊
- 進程理論和GIL鎖
- 死鎖與遞歸鎖
- 多線程與守護線程
- 定時器-條件-隊列
- 線程池與進程池(新方法)
- 協程與IO模型
- 協程理論知識
- gevent與greenlet模塊
- 5種網絡IO模型
- 非阻塞與多路復用IO實現
- 帶著目標學python
- Pycharm基本使用
- 爬蟲
- 案例-爬mzitu美女
- 案例-爬小說
- beautifulsoup解析模塊
- etree中的xpath解析模塊
- 反爬對抗-普通驗證碼
- 反爬對抗-session登錄
- 反爬對抗-代理池
- 爬蟲技巧-線程池
- 爬蟲對抗-圖片懶加載
- selenium瀏覽器模擬