python函数修饰符@的作用是为现有函数增加额外的功能,常用于插入日志、性能测试、事务处理等等。
创建函数修饰符的规则:
(1)修饰符是一个函数
(2)修饰符取被修饰函数为参数
(3)修饰符返回一个新函数
(4)修饰符维护被维护函数的签名
例1:被修饰函数不带参数
>>> def decorator(funx):
def wrap_func():
print("开始...")
funx()
print("结束...")
return wrap_func
>>> @decorator
def fun_need_decorate():
print("Hello,world")
>>> fun_need_decorate()
开始...
Hello,world
结束...
>>> print(fun_need_decorate.__name__)
wrap_func ##函数名被修改了
幸运的是Python提供给我们一个简单的函数来解决这个问题,那就是functools.wraps。我们修改上一个例子来使用functools.wraps:
>>> from functools import wraps
>>> def decorator(funx):
@wraps(funx)
def wrap_func():
print("开始...")
funx()
print("结束...")
return wrap_func
>>> @decorator
def fun_need_decorate():
print("Hello,world")
>>> fun_need_decorate()
开始...
Hello,world
结束...
>>> print(fun_need_decorate.__name__)
fun_need_decorate
例2:被修饰函数带参数
>>> from functools import wraps
>>> def decorator_rect(func):
@wraps(func)
def wrap_rect(*args):
print("矩形的:",end='')
print(func(*args))
print("end")
return wrap_rect
>>> @decorator_rect
def perimeter(x,y):
print("周长是:",end='')
return 2 *(x+y)
>>> @decorator_rect
def area(x,y):
print("面积是:",end='')
return x * y
>>> perimeter(5,6)
矩形的:周长是:22
end
>>> area(5,6)
矩形的:面积是:30
end
>>> print(perimeter.__name__,area.__name__)
perimeter area
*args的用法见:
https://blog.csdn.net/qq_40816848/article/details/104419246
应用场景
日志是装饰器运用的另一个亮点。
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
带参数的装饰器
来想想这个问题,难道@wraps不也是个装饰器吗?但是,它接收一个参数,就像任何普通的函数能做的那样。那么,为什么我们不也那样做呢?
在函数中嵌入装饰器
from functools import wraps
import os
def logit(file_name = 'out.log'):
def decorator_log(func):
@wraps(func)
def wrap_func(*args,**kwargs):
log_string = func.__name__ + " was called."
file_path = func(*args,**kwargs)
file_file = os.path.join(file_path,file_name)
print(file_file)
with open(file_file,'w') as opened_file:
opened_file.write(log_string + '\n')
return wrap_func
return decorator_log
@logit('out_1.log')
def myfun2(path):
return path
myfun1(r'C:\Users\Yoke\Desktop\test')
# Output: myfunc1 was called
# 现在一个叫做 out.log 的文件出现了,里面的内容就是上面的字符串
myfun2(r'C:\Users\Yoke\Desktop\test')
# Output: myfunc2 was called
# 现在一个叫做 out_1.log 的文件出现了,里面的内容就是上面的字符串
装饰器类
待续…
内置的修饰符
内置修饰符有三个,分别是 staticmethod、classmethod 和 property,作用分别是把类中定义的实例方法变成静态方法、类方法和类属性
staticmethod 修饰符
https://www.runoob.com/python/python-func-staticmethod.html
classmethod 修饰符
https://www.runoob.com/python/python-func-classmethod.html