Python 中的裝飾器

一, 引用

[書] 流暢的Python

[書] Effective Python

二, 基本概念

Python 中的裝飾器

問題1:裝飾器是什么?

解答: 嚴格來說,裝飾器只是語法糖, 裝飾器是可調用的對象,可以像常規的可調用對象那樣調用,特殊的地方是裝飾器的參數是一個函數

問題2:裝飾器有什么特性?

解答: 裝飾器有2個特性,一是可以把被裝飾的函數替換成其他函數, 二是可以在加載模塊時候立即執行

def?decorate(func):

????print(‘running decorate’,?func)

????def?decorate_inner():

????????print(‘running decorate_inner function’)

????????return?func()

????return?decorate_inner

 

<a?href=“http://www.ahoiyf.live/members/decorate”>@decorate</a>

def?func_1():

????print(‘running func_1’)

 

if?__name__?==?‘__main__’:

 

????print(func_1)

 

#返回值

running?decorate?<function func_1?at?0x7f29f644d268>

<function?decorate.<locals>.decorate_inner?at?0x7f29f641cb70>

問題3:如何使用被裝飾函數中的參數?

解答: 通過args 和 *kwargs 傳遞被修飾函數中的參數

def?decorate(func):

????def?decorate_inner(*args,?**kwargs):

????????print(type(args),?type(kwargs))

????????print(‘args’,?args,?‘kwargs’,?kwargs)

????????return?func(*args,?**kwargs)

????return?decorate_inner

 

<a?href=“http://www.ahoiyf.live/members/decorate”>@decorate</a>

def?func_1(*args,?**kwargs):

????print(args,?kwargs)

 

if?__name__?==?‘__main__’:

 

????func_1(‘1’,?‘2’,?‘3’,?para_1=‘1’,?para_2=‘2’,?para_3=‘3’)

 

#返回值

<class?‘tuple’> <class?‘dict’>

args?(‘1’,?‘2’,?‘3’)?kwargs?{‘para_2’:?‘2’,?‘para_1’:?‘1’,?‘para_3’:?‘3’}

(‘1’,?‘2’,?‘3’)?{‘para_2’:?‘2’,?‘para_1’:?‘1’,?‘para_3’:?‘3’}

三, 疊放裝飾器

Python 中的裝飾器

問題1:疊放裝飾器執行順序是什么?

解答: 如果一個函數被多個裝飾器修飾,其實應該是該函數先被最里面的裝飾器修飾后(下面例子中函數main()先被inner裝飾,變成新的函數),變成另一個函數后,再次被裝飾器修飾

def?outer(func):

????print(‘enter outer’,?func)

????def?wrapper():

????????print(‘running outer’)

????????func()

????return?wrapper

 

def?inner(func):

????print(‘enter inner’,?func)

????def?wrapper():

????????print(‘running inner’)

????????func()

????return?wrapper

 

@outer

@inner

def?main():

????print(‘running main’)

 

if?__name__?==?‘__main__’:

 

????main()

 

#返回值

 

enter?inner?<function main?at?0x7fa1c96e8b70>

enter?outer?<function?inner.<locals>.wrapper?at?0x7fa1c96e8bf8>

running outer

running inner

running?main

四, 標準庫中的裝飾器

Python 中的裝飾器

問題1: 標準庫中都有哪些裝飾器?

解答: 標準庫中有多種裝飾器, 例如:裝飾方法的函數有property, classmethod, staticmethod; functools模塊中的lru_cache, singledispatch, ?wraps 等等

from?functools?import?lru_cache

from?functools?import?singledispatch

from?functools?import?wraps

問題2:為什么要使用@wraps裝飾器?它的作用是什么?

解答: 使用裝飾器會產生我們可能不希望出現的副作用, 例如:改變被修飾函數名稱,對于調試器或者對象序列化器等需要使用內省機制的那些工具,可能會無法正常運行;其實調用裝飾器后,會將同一個作用域中原來函數同名的那個變量(例如下面的func_1),重新賦值為裝飾器返回的對象;使用@wraps后,會把與內部函數(被修飾函數,例如下面的func_1)相關的重要元數據全部復制到外圍函數(例如下面的decorate_inner)

from?functools?import?wraps

 

def?decorate(func):

????print(‘running decorate’,?func)

????@wraps(func)

????def?decorate_inner():

????????print(‘running decorate_inner function’,?decorate_inner)

????????return?func()

????return?decorate_inner

 

<a?href=“http://www.ahoiyf.live/members/decorate”>@decorate</a>

def?func_1():

????print(‘running func_1’,?func_1)

 

if?__name__?==?‘__main__’:

 

????func_1()

 

#返回值

running?decorate?<function func_1?at?0x7f145d2c2268>

running decorate_inner?function?<function func_1?at?0x7f145b9731e0>

running?func_1?<function func_1?at?0x7f145b9731e0>

五, 裝飾器設計模式

Python 中的裝飾器

問題1: 什么是裝飾器設計模式?

解答: 動態的給一個對象添加一些額外的職責,就擴展功能而言,裝飾器模式比子類化更加靈活,在設計模式中,裝飾器和組件都是抽象類,為了給具體的組件添加行為,具體的裝飾器實例要包裝具體組件的實例,即,裝飾器和所裝飾的組件接口一致,對使用該組建的客戶透明,將客戶的請求轉發給該組件,并且可能在轉發前后執行一些額外的操作,透明性使得可以遞歸嵌套多個裝飾器,從而可以添加任意多個功能

問題2: Python中的裝飾器函數和設計模式中的裝飾器模式有什么關系?

解答: ?修飾器模式和Python修飾器之間并不是一對一的等價關系, Python裝飾器函數更為強大,不僅僅可以實現裝飾器模式。

相關新聞

聯系我們

400-080-6560

在線咨詢:點擊這里給我發消息

郵件:[email protected]

工作時間:周一至周日,09:00-18:30

QR code
云南快乐10分开奖直播 快赢彩票游戏 自助售饮料机赚钱 走路 骑行能赚钱的软件 酷彩娱乐群 赚钱心得体会800 小程序 代理赚钱吗 捕鱼大亨2015 赚钱给孩子长大 百家号视频点击率赚钱 彩九安卓 开劳务工公司赚钱吗 学校奶茶店赚钱吗 6538彩票苹果 买卖二手车怎么赚钱吗 天天网赚app下载赚钱 贵州麻将上下分找代理