本文重点:解决了类里面定义的装饰器,在同一个类里面使用的问题,并实现了装饰器的类属性参数传递
目录:
一、基本装饰器
二、在类里定义装饰器,装饰本类内函数
三、类装饰器
正文:
一、基本装饰器
装饰不带参数的函数
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)
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。