Python装饰器以及高级用法( 四 )


class ImportantStuff(object): @time_this def do_stuff_1(self): ... @time_this def do_stuff_2(self): ... @time_this def do_stuff_3(self): ...这样就可以了 。但是这个类中还有一些额外的代码行 。如果我们写一些更多的类方法并忘记装饰它们中的一个呢?如果我们决定不再为进行计时怎么办?这里肯定存在人为错误的空间 。这样编写它会好得多:
@time_all_class_methodsclass ImportantStuff: def do_stuff_1(self): ... def do_stuff_2(self): ... def do_stuff_3(self): ...如你所知,该代码相当于:
class ImportantStuff: def do_stuff_1(self): ... def do_stuff_2(self): ... def do_stuff_3(self): ...ImportantStuff = time_all_class_methods(ImportantStuff)那么time_all_class_methods是如何工作的? 首先,我们知道它需要将一个类作为参数,并返回一个类 。我们也知道返回类的函数应该与原始ImportantStuff类的函数相同 。也就是说,我们仍然希望想要完成重要的事情,我们需要进行计时 。以下是我们将如何做到这一点:
def time_this(original_function):print ("decorating")def new_function(*args,**kwargs): print ("starting timer")import datetimebefore = datetime.datetime.now()x = original_function(*args,**kwargs)after = datetime.datetime.now()print ("Elapsed Time = {0}".format(after-before))return xreturn new_function def time_all_class_methods(Cls): class NewCls(object): def __init__(self,*args,**kwargs): self.oInstance = Cls(*args,**kwargs) def __getattribute__(self,s): """ 每当访问NewCls对象的任何属性时,都会调用这个函数 。这个函数首先尝试 从NewCls获取属性 。如果失败,则尝试从self获取属性 。oInstance(一个 修饰类的实例) 。如果它设法从self获取属性 。oInstance, 属性是一个实例方法,然后应用' time_this ' 。""" try:x = super(NewCls,self).__getattribute__(s) except AttributeError:pass else: return x x = self.oInstance.__getattribute__(s) if type(x) == type(self.__init__): # 这是一个实例方法 return time_this(x) # 这等价于用time_this修饰方法 else: return x return NewCls#现在让我们做一个虚拟类来测试它:@time_all_class_methodsclass Foo(object): def a(self): print ("entering a") import time time.sleep(3) print ("exiting a")oF = Foo()oF.a()结论在装饰器的高级用法中,我向你展示了使用Python装饰器的一些技巧 - 我已经向你展示了如何将参数传递给装饰器,以及如何装饰类 。但这仍然只是冰山的一角 。在各种奇怪的情况下,有大量的方法用于装饰器 。你甚至可以装饰你的装饰器(但如果你到达那一点,那么做一个全面的检查可能是个好主意) 。Python同时内置了一些值得了解的装饰器,例如装饰器staticmethod及classmethod 。
接下来要怎么做?除了我在这篇文章中向你展示的内容外,通常不需要对装饰器执行任何更复杂的操作 。如果你对更改类功能的更多方法感兴趣,那么我建议阅读有关继承和一般OO设计原则的数据 。或者,如果你真的想学会他们,那么请阅读元类(但同样,处理这些东西几乎不需要) 。

【Python装饰器以及高级用法】


推荐阅读