前言
装饰器本质上是一个Python函数,它可以让其他函数在不需要做任务代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
常见装饰器:内置装饰器、类装饰器、函数装饰器、带参数的函数装饰器
实战
原始方法使用:
def use_logging(func_name):
print("[debug] %s is running" %func_name )
def bar():
use_logging("bar")
print("i am bar")
def bar2():
use_logging("bar2")
print("i am bar2")
bar()
bar2()
输出:
[debug] bar is running
i am bar
[debug] bar2 is running
i am bar2
函数装饰器古老的方式实现:
def use_logging(func):
# print("[debug] %s is running" %func_name )
def wrapper(*args, **kwargs):
print("[debug] %s is running" % func.__name__)
return func(*args, **kwargs)
return wrapper()
def bar():
# use_logging("bar")
print("i am bar")
def bar2():
# use_logging("bar2")
print("i am bar2")
bar = use_logging(bar)
bar2 = use_logging(bar2)
输出:
[debug] bar is running
i am bar
[debug] bar2 is running
i am bar2
这种方式比较麻烦,每次都要是要使用use_logging函数,所以进一步实现
函数装饰器实现:
def use_logging(func):
# print("[debug] %s is running" %func_name )
def wrapper(*args, **kwargs):
print("[debug] %s is running" % func.__name__)
return func(*args, **kwargs)
return wrapper()
@use_logging
def bar():
# use_logging("bar")
print("i am bar")
@use_logging
def bar2():
# use_logging("bar2")
print("i am bar2")
输出:
[debug] bar is running
i am bar
[debug] bar2 is running
i am bar2
可以看到使用了@use_logging代替了bar = use_logging(bar),但是结果还是不变的。
带参数的函数装饰器:
def use_logging(level = "debug"):
def decorator(func):
def wrapper(*args, **kwargs):
print("[%s] %s is running" % (level, func.__name__))
return func(*args, **kwargs)
return wrapper()
return decorator
@use_logging("info")
def bar():
# use_logging("bar")
print("i am bar")
@use_logging("debug")
def bar2():
# use_logging("bar2")
print("i am bar2")
类装饰器的使用:
class Foo(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print(" class decorator running")
self.func()
print(" class decorator ending")
@Foo
def bar():
print("i am bar")
bar()
输出:
class decorator running
i am bar
class decorator ending
内置装饰器使用:
class Student(object):
def __init__(self,name,score):
self.name = name
self.__score = score
@property
def score(self):
return self.__score
@score.setter
def score(self,score):
if score < 0 or score > 100:
raise ValueError("invalid score")
self.__score = score
s = Student("jarvis","100")
s.score = 99
print(s.score)
输出:
99
修改 s.score = 101,此时输出报错
这里可以看到,内置装饰器的作用是可以判断修改的变量是否符合预期,不符合就报错