这里说类装饰器,就不得不说一个特殊的函数__call__
在Python中,函数其实就是一个对象:
>>> f = abs >>> f.__name__ 'abs' >>> f(-123) 123
由于f可以被调用,所以f被称为可调用对象
所有的函数都是可调用对象
一个类实例也可以变成一个可调用对象,只需要实现一个特殊的方法__call__()
我们把Person类变成一个可调用对象
class Person(object): def __init__(self, name, gender): self.name = name self.gender = gender def __call__(self, friend): print 'My name is %s...' % self.name print 'My friend is %s...' % friend
现在可以对Person实例直接调用
>>> p = Person('Bob', 'male') >>> p('Tim') My name is Bob... My friend is Tim...
这样的话,也就是说我们可以把类写成装饰器
class Deco:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
return self.func(*args, **kwargs)
@Deco
def foo(x, y):
return x ** y
# 过程解析
fn = Deco(foo)
foo = fn
foo(12, 34)
下面写一个在工作中常用的重试装饰器的简单实现Retry
import time
class retry(object):
def __init__(self, max_retries=3, wait=0, exceptions= (Exception,)):
self.max_retries = max_retries
self.exceptions = exceptions
self.wait = wait
def __call__(self, func):
def wrapper(*args, **kwargs):
for i in range(self.max_retries + 1):
try:
result = func(*args, **kwargs)
except self.exceptions:
time.sleep(self.wait)
continue
else:
return result
return wrapper