4.1 在类中定义装饰器
以实例或者以类方法的形式进行应用
代码解析:
from functools import wraps class A: # Decorator as an instance method def decorator1(self, func): @wraps(func) def wrapper(*args, **kwargs): print('Decorator 1') return func(*args, **kwargs) return wrapper # Decorator as a class method @classmethod def decorator2(cls, func): @wraps(func) def wrapper(*args, **kwargs): print('Decorator 2') return func(*args, **kwargs) return wrapper # As an instance method a = A() @a.decorator1 def spam(): pass # As a class method @A.decorator2 def grok(): pass # 这种方法在标准库中就有示例,比如说@property,实际是拥有 # getter()/setter()/deleter()方法的类,类中每一个定义的方 # 法可以作为装饰器 # 比如代码如下: class Person: # Create a property instance first_name = property() # Apply decorator methods @first_name.getter def first_name(self): return self._first_name @first_name.setter def first_name(self, value): if not isinstance(value, str): raise TypeError('Expected a string') self._first_name = value
4.2 把装饰器定义为类
定义中需要实现__call__(),__get__() 方法
# 把装饰器定义为类 # 定义中需要实现__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): return x + y # 在类中使用装饰器 class Spam: @Profiled def bar(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