经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Python » 查看文章
类装饰器
来源:cnblogs  作者:从python开始  时间:2018/11/14 10:03:16  对本文有异议

  在理解类装饰器之前,先回忆一下有关装饰器的知识。装饰器本质上就是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器的返回值也是一个函数对象(函数的引用)。

 

__call__方法
  一个对象是否可调用,看其中是否实现了__call__方法。例如,类的对象是不可调用的,因为其中没有实现__call__方法。如果我们在一个类中定义了__call__方法,那么这个类对象将变得可调用。只要某个对象定义了__call__()方法,那么这个对象就是callable的。

  1. 类中没有实现__call__方法:
  2. >>> class A: # 类中没有实现__call__方法
  3. ...     pass
  4. >>> a = A()
  5. >>> a() # 类对象不可调用
  6. Traceback (most recent call last):
  7.   File "<stdin>", line 1, in <module>
  8. TypeError: 'A' object is not callable
  9. 类中实现了__call__方法:
  10. >>> class B:
  11. ...     def __init__(self):
  12. ...         self.name = 'zhangsan'
  13. ...     def __call__(self): # 类中实现了__call__方法
  14. ...         print('类中实现了__call__方法:', self.name)
  15. ... 
  16. >>> b = B()
  17. >>> b() # 类对象可调用,并在调用类对象的时候,自动执行__call__方法
  18. 类中实现了__call__方法: zhangsan

 

类装饰器
  类装饰器本质上和函数装饰器原理、作用相同,都是为其它函数增加额外的功能。但是相比于函数装饰器,类装饰器具有灵活度大、高内聚、封装性等优点。使用类装饰器可以直接依靠类内部的__call__方法来实现,当使用 @ 形式将类装饰器附加到函数上时,就会调用类装饰器的__call__方法。而不需要向函数装饰器那样,在装饰器函数中定义嵌套函数,来实现装饰功能。
  使用类装饰器为一个函数的执行增加计时功能。

  1. >>> import time
  2. >>> class Foo():
  3. ...     def __init__(self, func): # 初始化函数中传入函数对象的参数
  4. ...         self._func = func
  5. ...     def __call__(self): # 定义__call__方法,直接实现装饰功能
  6. ...         start_time = time.time()
  7. ...         self._func()
  8. ...         end_time = time.time()
  9. ...         print('花费了 %.2f' % (end_time - start_time))
  10. ... 
  11. >>> @Foo  # bar=Foo(bar)
  12. ... def bar():
  13. ...     print('bar函数的执行时间为:')
  14. ...     time.sleep(2.5)
  15. ... 
  16. >>> bar() # bar=Foo(bar)(),没有嵌套关系了,直接执行Foo的 __call__方法,实现装饰功能
  17. bar函数的执行时间为:
  18. 花费了 2.51
  1. 上面的@Foo相当于bar = Foo(bar),等号左边的bar是类Foo的实例对象,等号右边的bar是类装饰器所装饰的函数名bar作为参数传递给类Foo。下面执行bar()即为调用类Foo的对象bar,此时会自动调用类中定义的__call__方法。
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号