码迷,mamicode.com
首页 > 编程语言 > 详细

python decorator 进阶

时间:2017-07-19 23:29:47      阅读:237      评论:0      收藏:0      [点我收藏+]

标签:产生   pes   blog   init   ogg   ati   括号   reference   enc   

转自:http://www.cnblogs.com/xybaby/p/6274283.html

上一篇文章开始的时候提到

 “一般来说,装饰器是一个函数,接受一个函数(或者类)作为参数,返回值也是也是一个函数(或者参数)”

有一般情况,就有特殊情况。第一种特殊情况:装饰器可能也是一个类;第二种特殊情况:装饰器返回的对象的类型不一定等同于被装饰对象的类型。

 
  对于第一种情况,我们知道对于任何callable的对象都可以进行调用(在对象名称后面使用小括号),callable对象的范围就比较广了
(user-defined functions, built-in functions, methods of built-in objects, class objects, methods of class instances, and certain class instances themselves are callable; extensions may define additional callable object types).

函数(方法)和类是callable,这个是很好理解的,如果一个类定义了__call__方法,那么该类的实例也是callable。另外,

     @dec
     def func():pass
  等价于: func = dec(func),所以如果dec是一个类,那么dec(func)是合理的,而被装饰后的func就变成了dec类的一个实例,如果dec类定义了__call__, 那么调用func(*)也是合理的,我们来看看修改后的代码
 
class cost_time_logger(object):
    def __init__(self, func):
        self.func = func
 
    def __call__(self, *args, **kwargs):
        import time
        begin = time.time()
        try:
            return self.func(*args, **kwargs)
        finally:
            print(func %s cost %s % (self.func.__name__, time.time() - begin))
 
@cost_time_logger
def complex_func(num):
    ret = 0
    for i in xrange(num):
        ret += i * i
    return ret
 
if __name__ == __main__:
    print complex_func(100000)

功能和上一篇文章的code snippet 0是一样的,但是type(complex_func) 变成了 <class ‘__main__.cost_time_logger‘>,这也说明了第二种情况:被装饰的对象原本是函数,被装饰之后变成了一个类实例。

  在pep-0318中,例举了一个用装饰器实现单例的例子,代码如下
def singleton(cls):
    instances = {}
    def getinstance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return getinstance
 
@singleton
class MyClass:
    pass
 
if __name__ == __main__:
    print type(MyClass)

 

MyClass被装饰前是一个类,被装饰后变成了一个function。
 
  笔者不是很喜欢这种改变被装饰对象的类型的实现方法,这种实现对代码的阅读者不是很友好,而且可能产生一些莫名其妙的BUG,浪费debug的时间。对于单例的例子,stackoverflow上也有其他的实现。
 
references:

python decorator 进阶

标签:产生   pes   blog   init   ogg   ati   括号   reference   enc   

原文地址:http://www.cnblogs.com/zhongguiyao/p/7208533.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!