**裝飾器 decorator**
裝飾器其本質就是一個函數,同樣使用 def 定義。
那它與與他函數有什么區別呢?
普通函數是實現某種特定功能,裝飾器是為被裝飾的函數添加附加功能,而不需去修改原函數(錦上添花)。
裝飾器特點:
1. 不修改被裝飾的原函數
2. 不修改被裝飾的原函數的調用方式
來個小示例:
假如你開發了一套后臺管理系統,有下面幾個功能:
~~~
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
def addUser():
print('添加用戶成功')
def delUser():
print('刪除用戶成功')
~~~
程序運行了一段時間,領導想知道調用每種方法的時間日志,你就開始編寫代碼
~~~
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import time
def log(funName):
time_str = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())
print("[%s] 執行了 %s 方法" % (time_str, funName))
def addUser():
log(addUser.__name__)
print('添加用戶成功')
def delUser():
log( delUser.__name__)
print('刪除用戶成功')
~~~
你信心滿滿的把代碼提交到代碼托管平臺上,過了會,項目經理把你叫到辦公室對你說:雖然你實現了功能,但是更改了生產環境中的代碼,這就違反了軟件開發中“開放-封閉”原則,即:已經實現的功能代碼不允許被修改,但可以被擴展
* 封閉:已實現的功能代碼塊不應該被修改
* 開放:對現有功能的擴展開放
于是 ,你就想到了《跟老司機學Python》這章說的裝飾器這種東西,完全符合 “開放-封閉”原則,繼續修改代碼
~~~
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import time
def log(func):
def warpper(*args, **kwargs):
time_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print("[%s] 執行了 %s 方法" %(time_str,func.__name__))
func(*args, **kwargs)
return warpper
@log #第一個
def addUser():
print('添加用戶成功')
@log #第二個
def delUser():
print('刪除用戶成功')
~~~
在函數的章節我們已經知道 : 函數即變量
對上面代碼中的兩個 @log 進行說明
~~~
第一個 @log 相當于 log(addUser)
第二個 @log 相當于 log(delUser)
~~~
從上面的程序可以看出:**裝飾器** 就是 **高階函數** 與 **嵌套函數** 的應用
這次提交代碼后,經理感覺你做的不錯,又提出了讓你添加是誰操作了每種方法的日志,你又接著修改代碼
~~~
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import time
name = 'air'#假設這是你存儲在 session 中的名字
def loger(who):
def log(func):
def warpper(*args,**kwargs):
time_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print("%s 在 [%s] 執行了 %s 方法" %(who,time_str,func.__name__))
func(*args, **kwargs)
return warpper
return log
@loger(name)
def addUser():
print('添加用戶成功')
@loger(name)
def delUser():
print('刪除用戶成功')
addUser()
delUser()
~~~
最終調用結果
~~~
air 在 [2017-10-06 17:14:17] 執行了 addUser 方法
添加用戶成功
air 在 [2017-10-06 17:14:17] 執行了 delUser 方法
刪除用戶成功
~~~
小伙子干的不錯,就等著升職加薪走上人生巔峰吧!
總結:
decorator 可以增強函數的功能,雖然編寫起來有點復雜,但是使用起來非常方便靈活。
- 跟老司機學Python
- 了解Python
- 1、python簡介
- 2、Python發展史
- 3、Python特點
- 4、Python解釋器
- 入坑Python
- 1、Python環境搭建
- 2、設置環境變量
- 3、開始使用Python
- 4、運行Python程序
- 掌握Python基礎
- Python基礎知識
- Python運算符
- 算術運算符
- 比較運算符
- 賦值運算符
- 邏輯運算符
- 位運算符
- 成員運算符
- 身份運算符
- 運算符優先級
- Python的變量與常量
- Python數據類型
- Number數值
- String字符串
- List列表
- Tuple元組
- Dictionary字典
- Set集合
- Python流程控制語句
- 條件判斷
- 循環控制
- Python函數
- 1、函數是什么
- 2、函數的定義
- 3、函數的參數
- 4、函數的調用
- 5、嵌套函數
- 6、遞歸函數
- 7、匿名函數
- 8、函數式編程
- 9、高階函數
- 1、map
- 2、reduce
- 3、filter
- 4、sorted
- 10、返回函數
- 11、偏函數
- Python文件IO操作
- 標準輸入輸出
- 讀寫文件
- with讀寫文件
- Python高級特性
- 1、列表生成式
- 2、迭代器
- 3、生成器
- 4、裝飾器
- Python模塊初探
- 1、模塊與包
- 2、創建模塊
- 3、模塊中的作用域
- 4、模塊的導入
- Python面向對象編程
- 類與對象
- 類的定義及使用
- 面向對象特性
- 類中的訪問域
- 查看對象詳情
- Python面向對象進階
- 類中的方法
- 類中的特殊成員
- 限制對象的屬性
- 再聊多繼承
- 裝x式創建類
- 創建元類
- Python內置模塊
- os模塊
- sys模塊
- random模塊
- time模塊
- datetime模塊
- shutil模塊
- collections模塊
- base64模塊
- json模塊
- hashlib模塊
- xml模塊
- 1. SAX解析XML
- 2. DOM解析XML
- 3. ElementTree解析XML
- urllib模塊
- logging模塊
- re模塊
- Python第三方模塊
- Pillow與PIL
- Requests
- Tablib
- Xpinyin
- Chardet
- Pycurl
- Virtualenv
- Python操作數據庫
- Mysql操作
- Sqllite操作
- Mongodb操作
- Redis操作
- Python的GUI編程
- Python中GUI的選擇
- Tkinter
- wxPython
- Socket網絡編程
- Socket網絡編程簡聊
- Socket內建方法
- TCP協議編程
- UDP協議編程
- TCP與UDP
- Python電子郵件
- SMTP發郵件
- POP3收郵件
- IMAP收郵件
- 進程線程
- 進程與線程
- 進程編程
- 使用進程池
- 進程間的通信
- 線程編程
- 使用線程鎖
- Python的GIL
- Web編程
- WSGI介紹
- Web框架
- Flask使用
- 模板jinjia2使用
- 項目結構規劃
- 異步與協程
- 概念掃盲
- 異步IO進化之路
- 協程是什么
- yield協程編程
- yield from
- asyncio
- async與await
- aiohttp之client
- aiphttp之server
- 網絡爬蟲
- 網絡爬蟲簡聊
- Beautiful Soup模塊的使用
- pyquery 模塊的使用
- selenium模塊的使用
- 爬取段子實例
- 錯誤與調試
- 錯誤
- 錯誤處理
- 拋出錯誤
- 高效的調試
- Python重要語句
- pass語句
- return語句
- Python開發必知
- pip使用詳解
- 如何對列表進行迭代
- 如何對字典進行迭代
- 字符串格式化
- 知識擴展
- 網絡模型
- GUI是什么