- 概念:类似于将函数包裹起来,实现同一功能的函数
- 功能:在代码运行期间动态增加功能的方式
一、知识准备
- 理解python中 *args 和 **kwargs
# 测试函数
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)
# 可以同时使用,但应注意顺序
def hi(name):
print("hi! ",name)
# 使用函数名作为变量
welcom = hi
welcom("xiaoming")
def hi(name='wangweiyang'):
print("now you are in insdie the hi() function")
# 定义内部函数
def greet()
print("now you are in the greet() function")
def welcome()
print("now you are in the welcome() function")
hi()
# 内部函数在外部是不能直接访问的
>>> greet() 错误
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())
def hi():
return "hi!wangweiyang!"
def doSomethingBeforeHi(func):
print("Do something before executing hi()")
print(func())
doSomethingBeforeHi(hi)
# 装饰函数
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
# 被装饰的函数
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)
# 装饰结果
a_function_requiring_decoration()
二、创建装饰器
# 装饰函数
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
# 使用@符号进行装饰
@a_new_decorator
def a_function_requiring_decoration():
"""
Please decorate me!
"""
print("The function which needs some decoration to remove or add something")
# 装饰结果
a_function_requiring_decoration()
- 使用装饰器会覆盖掉(重写)原函数本身的一些函数属性
# 输出函数本身名称
print(a_function_requiring_decoration.__name__)
# output:wrapTheFuction()
print(a_function_requiring_decoration.__doc__)
# output:None
- 使用functools.wraps来解决函数属性的问题
# 引入wraps
from functools import wraps
# 装饰函数
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
# 使用@符号进行装饰
@a_new_decorator
def a_function_requiring_decoration():
"""
Please decorate me!
"""
print("The function which needs some decoration to remove or add something")
# 装饰结果
a_function_requiring_decoration()
print(a_function_requiring_decoration.__name__)
# output: a_function_requiring_decoration
三、装饰器的使用场景
- 授权(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
四、装饰器进阶
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,并写入内容
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')
# 发送一个通知
self.notify()
return func(*args,**kwargs)
return wrappend_function
def notify(self):
# logit只打开日志
pass
@logit()
def myfunc1():
pass
class email_logit(logit):
"""
一个logit的实现版本,可以在函数调用时发送email给管理员
"""
def __init__(self,email="xxx@qq.com",*args,**kwargs):
self.email = email
super(email_logit,self).__init__(*args,**kwargs)
def notify(self):
# 发送一封邮件给管理员
pass
网友评论