本文重点:解决了类里面定义的装饰器,在同一个类里面使用的问题,并实现了装饰器的类属性参数传递
目录:
一、基本装饰器
二、在类里定义装饰器,装饰本类内函数
三、类装饰器
正文:
一、基本装饰器
装饰不带参数的函数
def clothes(func):
def wear():
print('Buy clothes!{}'.format(func.__name__))
return func()
return wear
@clothes
def body():
print('The body feels could!')
#备注:@是语法糖
# 不用语法糖的情况下,使用下面语句也能实现装饰作用:把body再加工,再传给body
# body = clothes(body)
装饰带一个参数的函数
def clothes(func):
def wear(anything): # 实际是定义一个anything参数,对应body函数参数
print('Buy clothes!{}'.format(func.__name__))
return func(anything) # 执行func函数,并传入调用传入的anything参数
# wear = func(anything) # 在这一步,实际上可以看出来,为啥wear必须带参数,因为它就是func(anything)
return wear
# 所以clothes的结果是
# clothes = wear = func(anything)
# 不用语法糖的情况下就是
# body = clothes(body)('hands')
# 进一步证明:print(body.__name__) 显示的是wear函数
@clothes
def body(part):
print('The body feels could!{}'.format(part))
body('hands')
装饰带不定长参数的函数
通常装饰器不只装饰一个函数,每个函数参数的个数也不相同
这个时候使用不定长参数*args,**kwargs
def clothes(func):
def wear(*args, **kwargs):
print('Buy clothes!{}'.format(func.__name__))
return func(*args, **kwargs)
return wear
@clothes
def body(part):
print('The body feels could!{}'.format(part))
@clothes
def head(head_wear, num=2):
print('The head need buy {} {}!'.format(num, head_wear))
body('hands')
head('headdress')
装饰器带参数
# 把装饰器再包装,实现了seasons传递装饰器参数。
def seasons(season_type):
def clothes(func):
def wear(*args, **kwargs):
if season_type == 1:
s = 'spring'
elif season_type == 2:
s = 'summer'
elif season_type == 3:
s = 'autumn'
elif season_type == 4:
s = 'winter'
else:
print('The args is error!')
return func(*args, **kwargs)
print('The season is {}!{}'.format(s, func.__name__))
return func(*args, **kwargs)
return wear
return clothes
@seasons(2)
def children():
print('i am children')
children()
二、在类里定义装饰器,装饰本类内函数:
类装饰器,装饰函数和类函数调用不同的类函数
把装饰器写在类里
在类里面定义个函数,用来装饰其它函数,严格意义上说不属于类装饰器。
class Buy(object):
def __init__(self, func):
self.func = func
# 在类里定义一个函数
def clothes(func): # 这里不能用self,因为接收的是body函数
# 其它都和普通的函数装饰器相同
def ware(*args, **kwargs):
print('This is a decrator!')
return func(*args, **kwargs)
return ware
@Buy.clothes
def body(hh):
print('The body feels could!{}'.format(hh))
body('hh')
装饰器装饰同一个类里的函数
背景:想要通过装饰器修改类里的self属性值。
class Buy(object):
def __init__(self):
self.reset = True # 定义一个类属性,稍后在装饰器里更改
self.func = True
# 在类里定义一个装饰器
def clothes(func): # func接收body
def ware(self, *args, **kwargs): # self,接收body里的self,也就是类实例
print('This is a decrator!')
if self.reset == True: # 判断类属性
print('Reset is Ture, change Func..')
self.func = False # 修改类属性
else:
print('reset is False.')
return func(self, *args, **kwargs)
return ware
@clothes
def body(self):
print('The body feels could!')
b = Buy() # 实例化类
b.body() # 运行body
print(b.func) # 查看更改后的self.func值,是False,说明修改完成
三、类装饰器
定义一个类装饰器,装饰函数,默认调用__call__方法
#
class Decrator(object):
def __init__(self, func): # 传送的是test方法
self.func = func
def __call__(self, *args, **kwargs): # 接受任意参数
print('函数调用CALL')
return self.func(*args, **kwargs) # 适应test的任意参数
@Decrator # 如果带参数,init中的func是此参数。
def test(hh):
print('this is the test of the function !',hh)
test('hh')
定义一个类装饰器,装饰类中的函数,默认调用__get__方法
实际上把类方法变成属性了,还记得类属性装饰器吧,@property
下面自已做一个property
class Decrator(object):
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
'''
instance:代表实例,sum中的self
owner:代表类本身,Test类
'''
print('调用的是get函数')
return self.func(instance) # instance就是Test类的self
class Test(object):
def __init__(self):
self.result = 0
@Decrator
def sum(self):
print('There is the Func in the Class !')
t = Test()
print(t.sum) # 众所周知,属性是不加括号的,sum真的变成了属性
做一个求和属性sum,统计所有输入的数字的和
class Decrator(object):
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
print('调用的是get函数')
return self.func(instance)
class Test(object):
def __init__(self, *args, **kwargs):
self.value_list = []
if args:
for i in args:
if str(i).isdigit():
self.value_list.append(i)
if kwargs:
for v in kwargs.values():
if str(v).isdigit():
self.value_list.append(v)
@Decrator
def sum(self):
result = 0
print(self.value_list)
for i in self.value_list:
result += i
return result
t = Test(1,2,3,4,5,6,7,8,i=9,ss=10,strings = 'lll')
print(t.sum)