python 类装饰器和函数装饰器区别_python进阶之装饰器之4在类中定义装饰器,将装饰器定义为类,两者的区别与联系...

# 把装饰器定义为类

# 定义中需要实现__call__(),__get__() 方法

import types

from functools import wraps

class Profiled:

def __init__(self, func):

wraps(func)(self)

self.ncalls = 0

def __call__(self, *args, **kwargs):

self.ncalls += 1

return self.__wrapped__(*args, **kwargs)

def __get__(self, instance, cls):

if instance is None:

return self

else:

return types.MethodType(self, instance)

# 在类外使用装饰器

@Profiled

def add(x, y):

re

4.1 在类中定义装饰器

以实例或者以类方法的形式进行应用

代码解析:

from functools importwrapsclassA:#Decorator as an instance method

defdecorator1(self, func):

@wraps(func)def wrapper(*args, **kwargs):print('Decorator 1')return func(*args, **kwargs)returnwrapper#Decorator as a class method

@classmethoddefdecorator2(cls, func):

@wraps(func)def wrapper(*args, **kwargs):print('Decorator 2')return func(*args, **kwargs)returnwrapper#As an instance method

a =A()

@a.decorator1defspam():pass

#As a class method

@A.decorator2defgrok():pass

#这种方法在标准库中就有示例,比如说@property,实际是拥有#getter()/setter()/deleter()方法的类,类中每一个定义的方#法可以作为装饰器#比如代码如下:

classPerson:#Create a property instance

first_name =property()#Apply decorator methods

@first_name.getterdeffirst_name(self):returnself._first_name

@first_name.setterdeffirst_name(self, value):if notisinstance(value, str):raise TypeError('Expected a string')

self._first_name= value

4.2 把装饰器定义为类

定义中需要实现__call__(),__get__() 方法

#把装饰器定义为类#定义中需要实现__call__(),__get__() 方法

importtypesfrom functools importwrapsclassProfiled:def __init__(self, func):

wraps(func)(self)

self.ncalls=0def __call__(self, *args, **kwargs):

self.ncalls+= 1

return self.__wrapped__(*args, **kwargs)def __get__(self, instance, cls):if instance isNone:returnselfelse:returntypes.MethodType(self, instance)#在类外使用装饰器

@Profileddefadd(x, y):return x +y#在类中使用装饰器

classSpam:

@Profileddefbar(self, x):print(self, x)print(add(2, 3)) #5

print(add(3, 3)) #6

print(add(4, 3)) #7

print(add.ncalls) #3

s=Spam()print(s.bar(1)) #<__main__.Spam object at 0x000001F39D74D4E0> 1

print(s.bar(2)) #<__main__.Spam object at 0x000001F39D74D4E0> 2

print(s.bar(3)) #<__main__.Spam object at 0x000001F39D74D4E0> 3

print(Spam.bar.ncalls) #3

print(s.bar.ncalls) #3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值