- 概念:類似于將函數(shù)包裹起來溜腐,實(shí)現(xiàn)同一功能的函數(shù)
- 功能:在代碼運(yùn)行期間動(dòng)態(tài)增加功能的方式
一党觅、知識(shí)準(zhǔn)備
- 理解python中 *args 和 **kwargs
# 測(cè)試函數(shù)
def test_args_kwargs(arg1,arg2,arg3):
print("arg1:",arg1)
print("arg2:",arg2)
print("arg3P:",arg3)
# 使用*args
args = ("two",3,5)
test_args_kwargs(*args)
# 使用 **kwargs
kwargs = {"arg3":5,"arg1":two,"arg2":3}
test_args_kwargs(**kwargs)
# 可以同時(shí)使用,但應(yīng)注意順序
- python 中的函數(shù)名稱也是對(duì)象(一切皆對(duì)象)
def hi(name):
print("hi! ",name)
# 使用函數(shù)名作為變量
welcom = hi
welcom("xiaoming")
def hi(name='wangweiyang'):
print("now you are in insdie the hi() function")
# 定義內(nèi)部函數(shù)
def greet()
print("now you are in the greet() function")
def welcome()
print("now you are in the welcome() function")
hi()
# 內(nèi)部函數(shù)在外部是不能直接訪問的
>>> greet() 錯(cuò)誤
def hi(name='wangweiyang'):
def greet():
return "now you are in the greet() function"
def welcome():
return "now you are in the welcome() function"
if name == "wangweiyang":
return greet
else:
return welcome
a = hi()
print(a)
print(a())
- 將函數(shù)作為參數(shù)傳遞給另一個(gè)函數(shù)
def hi():
return "hi!wangweiyang!"
def doSomethingBeforeHi(func):
print("Do something before executing hi()")
print(func())
doSomethingBeforeHi(hi)
# 裝飾函數(shù)
def a_new_decorator(a_func):
def wrapTheFunction():
print("Do some work before executing a_func()")
a_func()
print("Do some work after executing a_func()")
return wrapTheFunction
# 被裝飾的函數(shù)
def a_function_requiring_decoration():
print("The function which needs some decoration to remove or add something")
# 裝飾過程
a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
# 裝飾結(jié)果
a_function_requiring_decoration()
二褒纲、創(chuàng)建裝飾器
- 使用@符號(hào):本質(zhì)上就是裝飾過程(簡(jiǎn)化與統(tǒng)一)
# 裝飾函數(shù)
def a_new_decorator(a_func):
def wrapTheFunction():
print("Do some work before executing a_func()")
a_func()
print("Do some work after executing a_func()")
return wrapTheFunction
# 使用@符號(hào)進(jìn)行裝飾
@a_new_decorator
def a_function_requiring_decoration():
"""
Please decorate me!
"""
print("The function which needs some decoration to remove or add something")
# 裝飾結(jié)果
a_function_requiring_decoration()
- 使用裝飾器會(huì)覆蓋掉(重寫)原函數(shù)本身的一些函數(shù)屬性
# 輸出函數(shù)本身名稱
print(a_function_requiring_decoration.__name__)
# output:wrapTheFuction()
print(a_function_requiring_decoration.__doc__)
# output:None
- 使用functools.wraps來解決函數(shù)屬性的問題
# 引入wraps
from functools import wraps
# 裝飾函數(shù)
def a_new_decorator(a_func):
@wraps(a_func)
# 使用wraps
def wrapTheFunction():
print("Do some work before executing a_func()")
a_func()
print("Do some work after executing a_func()")
return wrapTheFunction
# 使用@符號(hào)進(jìn)行裝飾
@a_new_decorator
def a_function_requiring_decoration():
"""
Please decorate me!
"""
print("The function which needs some decoration to remove or add something")
# 裝飾結(jié)果
a_function_requiring_decoration()
print(a_function_requiring_decoration.__name__)
# output: a_function_requiring_decoration
三楼雹、裝飾器的使用場(chǎng)景
- 授權(quán)(Authorization)-Django與Flask框架
from functools import wraps
def requires_auth(f):
@wraps(f)
def decorated(*args,**kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username,auth.password):
authenticate()
return f(*args,**kwargs)
return decorated
from functools import wraps
def logit(func):
@wraps(func)
def with_logging(*args,**kwargs):
print(func.__name__ + "was called")
return func(*args,**kwargs)
return with_logging
@logit
def addition_func(x):
"""Do some math"""
return x+x
result = addition_func(4)
# Output:addition_func was called
四脐雪、裝飾器進(jìn)階
- 在函數(shù)中嵌入裝飾器(可以接收函數(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 opend_file:
# 將日志寫入指定的logfile
opend_file.write(log_string + "\n")
return func(*args,**kwargs)
return wrapped_function
return logging_decorator
@logit
def myfunc1():
pass
myfunc1()
@logit(logfile='func2.log')
def myfunc2():
pass
myfunc2
from functools import wraps
class logit(object):
def __init__(self,logfile='out.log'):
self.logfile = logfile
def __call__(self,func):
@wraps(func)
def wrapper_function(*args,**kwargs):
log_string = func.__name__ + "was called"
print(log_string)
# 打開logfile并寫入
with open(self.logfile,'a') as opend_file:
# 將日志寫入指定的文件
opened_file.write(log_string + '\n')
# 發(fā)送一個(gè)通知
self.notify()
return func(*args,**kwargs)
return wrappend_function
def notify(self):
# logit只打開日志
pass
@logit()
def myfunc1():
pass
class email_logit(logit):
"""
一個(gè)logit的實(shí)現(xiàn)版本筛欢,可以在函數(shù)調(diào)用時(shí)發(fā)送email給管理員
"""
def __init__(self,email="xxx@qq.com",*args,**kwargs):
self.email = email
super(email_logit,self).__init__(*args,**kwargs)
def notify(self):
# 發(fā)送一封郵件給管理員
pass