python装饰器的使用
1、python装饰器的作用是什么?
它可以使我们的代码看起来更简洁,可以修改部分函数功能,让你的代码看起来很“高级”,当然,它也可能会造成代码的阅读性变差,所以在使用装饰器的时候,你需要做一个取舍。
2、当一个函数使用一个装饰器的时候发生了什么?
首先来看一段代码:
def param_func():
return "hi, im a function"
def decoration(function):
print("hi, im a decoration")
print(function)
decoration(param_func)
相信大家一眼就能看明白,python中函数是可以作为另一个函数的参数的,实际上,这就已经创建了一个装饰器,简单修改一下上面的代码使其看起来更像装饰器:
def name():
print("hi, im zhangSan")
def decoration(name):
def set_sex_age():
print("hi, im a boy")
name()
print("hi, im 16 years old")
return set_sex_age
name = decoration(name)
name()
上面这段代码描述的就是函数装饰器所作的事情,它封装一个函数且修改其行为,现在,我们换成使用@符号来修改上面这段代码:
def decoration(name):
def set_sex_age():
print("hi, im a boy")
name()
print("hi, im 16 years old")
return set_sex_age
@decoration
def name():
print("hi, im zhangSan")
name()
这里存在了一个问题,如果你打印name.__name__,就会发现输出是set_sex_age,函数名字被重写了,因此可以使用下面的方式来解决:
from functools import wraps
def decoration(name):
@wraps(name)
def set_sex_age():
print("hi, im a boy")
name()
print("hi, im 16 years old")
return set_sex_age
@decoration
def name():
print("hi, im zhangSan")
name()
print(name.__name__)
3、带参数的装饰器:
同样,使用装饰器也可以带参数,它的好处就不用说明了:
from functools import wraps
def people_decoration(age=16):
def decoration(name):
@wraps(name)
def set_sex_age():
print("hi, im a boy")
name()
print(f"hi, im {age} years old")
return set_sex_age
return decoration
@people_decoration(age=18)
def zhangSan():
print("hi, im zhangSan")
@people_decoration()
def liSi():
print("hi, im liSi")
zhangSan()
liSi()
4、装饰器类:
装饰器类的好处之一就是可以被继承:
from functools import wraps
class People_decoration(object):
def __init__(self, sex='boy', age='16'):
self.sex = sex
self.age = age
def __call__(self, name):
@wraps(name)
def decoration(*args, **kwargs):
print(f"hi, im a {self.sex}")
name()
print(f"hi, im {self.age} years old")
return decoration
@People_decoration()
def zhangSan():
print("hi, im zhangSan")
@People_decoration(sex="girl", age="18")
def liSi():
print("hi, im liSi")
zhangSan()
liSi()
其中用到了__call__,可以简单理解为__call__()重载了(),使得类的实例对象可以直接像调用普通函数那样直接调用:对象名()