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


@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 。
【Python|Python装饰器以及高级用法】接下来要怎么做?除了我在这篇文章中向你展示的内容外 , 通常不需要对装饰器执行任何更复杂的操作 。 如果你对更改类功能的更多方法感兴趣 , 那么我建议阅读有关继承和一般OO设计原则的数据 。 或者 , 如果你真的想学会他们 , 那么请阅读元类(但同样 , 处理这些东西几乎不需要) 。