您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“Python中裝飾器代碼是怎么樣的”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Python中裝飾器代碼是怎么樣的”這篇文章吧。
所有東西都是對象(函數(shù)可以當(dāng)做對象傳遞)
由于函數(shù)也是一個對象,而且函數(shù)對象可以被賦值給變量,所以,通過變量也能調(diào)用該函數(shù)。
def function_one(): print("測試函數(shù)") #可以將一個函數(shù)賦值給一個變量,比如 foo =function_one #這里沒有在使用小括號,因為我們并不是在調(diào)用function_one函數(shù),而是在將它放在foo變量里。 foo() ''' 測試函數(shù) Process finished with exit code 0 '''
閉包的概念:
1)函數(shù)嵌套
2)內(nèi)部函數(shù)使用外部函數(shù)的變量
3)外部函數(shù)的返回值為內(nèi)部函數(shù)
示例:
def outer_function(message): def inner_function(): print(message) return inner_function func = outer_function("你好") func() #你好
裝飾器的作用就是 不修改源代碼以及原函數(shù)調(diào)用方式的情況下 給原函數(shù)增加新的功能。
#將函數(shù)作為參數(shù)傳給另一個函數(shù) def decorator_function(original_function): def wrapper_function(): print('wrapper executed this before {}'.format(original_function.__name__)) original_function() return wrapper_function ''' 返回wrapper_function而不是wrapper_function();這是因為當(dāng)你把一對小括號放在后面,這個函數(shù)就會執(zhí)行; 然而如果你不放括號在它后面,那它可以被到處傳遞,并且可以賦值給別的變量而不去執(zhí)行它。 ''' def display(): print('display function ran') decorator_display = decorator_function(display) decorator_display()
運(yùn)行結(jié)果:
wrapper executed this before display display function ran Process finished with exit code 0
def decorator_function(original_function): def wrapper_function(): print('wrapper executed this before {}'.format(original_function.__name__)) original_function() return wrapper_function @decorator_function def display(): #等價于display =decorator_function(display) print('display function ran') display()
運(yùn)行結(jié)果:
wrapper executed this before display
display function ranProcess finished with exit code 0
def decorator_function(original_function): def wrapper_function(*args,**kwargs): print('wrapper executed this before {}'.format(original_function.__name__)) original_function(*args,**kwargs) return wrapper_function @decorator_function def display(): print('display function ran') @decorator_function def display_info(name,age): print('display_info ran with arguments ({},{})'.format(name,age)) display() print('='*50) display_info('Michal',20)
運(yùn)行結(jié)果:
wrapper executed this before display
display function ran
==================================================
wrapper executed this before display_info
display_info ran with arguments (Michal,20)Process finished with exit code 0
運(yùn)行如下代碼會出現(xiàn)一個問題
def decorator_function(original_function): def wrapper_function(*args,**kwargs): print('wrapper executed this before {}'.format(original_function.__name__)) original_function(*args,**kwargs) return wrapper_function @decorator_function def display(): print('display function ran') @decorator_function def display_info(name,age): print('display_info ran with arguments ({},{})'.format(name,age)) display_info = decorator_function(display_info) print(display_info.__name__)
wrapper_function
Process finished with exit code 0
輸出的應(yīng)該是display_info,這里的函數(shù)被wrapper_function替代了,重寫了我們函數(shù)的名字和注釋文檔(docstring)。Python中可以使用functools.wraps來解決這個問題。
from functools import wraps def decorator_function(original_function): @wraps(original_function) def wrapper_function(*args,**kwargs): print('wrapper executed this before {}'.format(original_function.__name__)) original_function(*args,**kwargs) return wrapper_function @decorator_function def display(): print('display function ran') @decorator_function def display_info(name,age): print('display_info ran with arguments ({},{})'.format(name,age)) display_info = decorator_function(display_info) print(display_info.__name__)
運(yùn)行結(jié)果:
display_info
Process finished with exit code 0
在函數(shù)中嵌入裝飾器
from functools import wraps def logit(logfile='out.log'): def logging_decorator(func): @wraps(func) def wrapped_function(*args, **kwargs): log_string = func.__name__ + " was called" print(log_string) # 打開logfile,并寫入內(nèi)容 with open(logfile, 'a') as opened_file: # 現(xiàn)在將日志打到指定的logfile opened_file.write(log_string + '\n') return func(*args, **kwargs) return wrapped_function return logging_decorator @logit() def myfunc1(): pass myfunc1() # Output: myfunc1 was called # 現(xiàn)在一個叫做 out.log 的文件出現(xiàn)了,里面的內(nèi)容就是上面的字符串 @logit(logfile='func2.log') def myfunc2(): pass myfunc2() # Output: myfunc2 was called # 現(xiàn)在一個叫做 func2.log 的文件出現(xiàn)了,里面的內(nèi)容就是上面的字符串
class myDecorator(object): def __init__(self, f): print("inside myDecorator.__init__()") f() # Prove that function definition has completed def __call__(self): print("inside myDecorator.__call__()") @myDecorator def aFunction(): print("inside aFunction()") print("Finished decorating aFunction()") aFunction()
運(yùn)行結(jié)果:
inside myDecorator.__init__() inside aFunction() Finished decorating aFunction() inside myDecorator.__call__() Process finished with exit code 0
被裝飾后的函數(shù)aFunction()實際上已經(jīng)是類myDecorator的對象。當(dāng)再調(diào)用aFunction()函數(shù)時,實際上就是調(diào)用類myDecorator的對象,因此會調(diào)用到類myDecorator的__call__()方法。
因此使用類作為裝飾器裝飾函數(shù)來對函數(shù)添加一些額外的屬性或功能時,一般會在類的__init__()方法中記錄傳入的函數(shù),再在__call__()調(diào)用修飾的函數(shù)及其它額外處理。
class entryExit(object): def __init__(self, f): self.f = f def __call__(self): print("Entering", self.f.__name__) self.f() print("Exited", self.f.__name__) @entryExit def func1(): print("inside func1()") @entryExit def func2(): print("inside func2()") func1() func2()
運(yùn)行結(jié)果:
Entering func1
inside func1()
Exited func1
Entering func2
inside func2()
Exited func2Process finished with exit code 0
空參:
from functools import wraps class decorator_class: def __init__(self): print('執(zhí)行decorator_class類的__init__()方法') def __call__(self, original_function): print('執(zhí)行decorator_class類的__call__()方法') @wraps(original_function) def wrapped_function(*args, **kwargs): print('call method executed this before {}'.format(original_function.__name__)) print('執(zhí)行' + original_function.__name__ + '()') original_function(*args, **kwargs) print(original_function.__name__ + '()執(zhí)行完畢') return wrapped_function @decorator_class() def display_info(name,age): print('display_info ran with arguments ({},{})'.format(name,age)) display_info('Michael',20)
運(yùn)行結(jié)果如下:
執(zhí)行decorator_class類的__init__()方法
執(zhí)行decorator_class類的__call__()方法
call method executed this before display_info
執(zhí)行display_info()
display_info ran with arguments (Michael,20)
display_info()執(zhí)行完畢Process finished with exit code 0
帶參數(shù):
from functools import wraps class decorator_class: def __init__(self,arg1, arg2): print('執(zhí)行decorator_class類的__init__()方法') self.arg1 =arg1 self.arg2=arg2 def __call__(self, original_function): print('執(zhí)行decorator_class類的__call__()方法') @wraps(original_function) def wrapped_function(*args, **kwargs): print('執(zhí)行wrapped_function()') print('call method executed this before {}'.format(original_function.__name__)) print('裝飾器參數(shù):', self.arg1, self.arg2) print('執(zhí)行' + original_function.__name__ + '()') original_function(*args, **kwargs) print(original_function.__name__ + '()執(zhí)行完畢') return wrapped_function @decorator_class('Hello', 'World') def display_info(name,age): print('display_info ran with arguments ({},{})'.format(name,age)) display_info('Michael',20)
運(yùn)行結(jié)果如下:
執(zhí)行decorator_class類的__init__()方法
執(zhí)行decorator_class類的__call__()方法
執(zhí)行wrapped_function()
call method executed this before display_info
裝飾器參數(shù): Hello World
執(zhí)行display_info()
display_info ran with arguments (Michael,20)
display_info()執(zhí)行完畢Process finished with exit code 0
示例2:
from functools import wraps class logit(object): def __init__(self, logfile='out.log'): self.logfile = logfile def __call__(self, func): @wraps(func) def wrapped_function(*args, **kwargs): log_string = func.__name__ + " was called" print(log_string) # 打開logfile并寫入 with open(self.logfile, 'a') as opened_file: # 現(xiàn)在將日志打到指定的文件 opened_file.write(log_string + '\n') # 現(xiàn)在,發(fā)送一個通知 self.notify() return func(*args, **kwargs) return wrapped_function def notify(self): # logit只打日志,不做別的 pass @logit() def myfunc1(): pass
#裝飾器1 def decorator1(func): #定義裝飾之后的函數(shù) def wrapper1(): # 裝飾器1 print('1-----裝飾1之前') # 調(diào)用基本函數(shù) func() # 擴(kuò)展功能2 print('1-----裝飾1之后') return wrapper1 #裝飾器2 def decorator2(func): #定義裝飾之后的函數(shù) def wrapper2(): # 裝飾器2 print('2-----裝飾2之前') # 調(diào)用基本函數(shù) func() # 擴(kuò)展功能2 print('2-----裝飾2之后') return wrapper2 #基本函數(shù) @decorator2 # 第二步:test = decorator2(eat) = test2 @decorator1 # 第一步:test = decorator1(eat) = test1 def test(): print('測試') #調(diào)用函數(shù) test()
運(yùn)行結(jié)果:
2-----裝飾2之前
1-----裝飾1之前
測試
1-----裝飾1之后
2-----裝飾2之后Process finished with exit code 0
以上是“Python中裝飾器代碼是怎么樣的”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。