python学习笔记(装饰器)

来源:互联网 发布:apache ant 1.8.2下载 编辑:程序博客网 时间:2024/05/16 05:30

本文大量参考了https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386819879946007bbf6ad052463ab18034f0254bf355000

仅作为个人学习笔记使用


我们希望增强函数的功能,但又不希望修改函数,这种在代码运行期间动态增加功能的方式,称之为“装饰器”。

装饰器大多数用在被装饰函数执行前或者执行后做特定的操作,比如参数处理,或者加上异常处理等等。

装饰器可以是一个函数,也可以是一个类,只要这个类实现了call函数。


好处:抽离出大量函数中与函数功能本身无关的雷同代码并继续重用


装饰器可以分为两类,一类是有参数的,一类是无参数的。

① 无参数的装饰器

def log(func):    def wrapper(*args, **kw):        print 'call %s(): ' % func.__name__        return func(*args, **kw)    return wrapper@logdef now():    print '2017-07-19'now()

运行结果是:

call now(): 2017-07-19

相当于执行了 

now = log(now)


② 带参数的装饰器:

def log(text):    def decorator(func):        def wrapper(*args, **kwargs):            print '%s %s():' % (text, func.__name__)            return func(*args, **kwargs)        return wrapper    return decorator@log('execute')def now():    print '2017-07-19'now()

运行结果如下:

execute now():2017-07-19

相当于执行了

now = log('execute')(now)



被装饰器装饰过后的函数__name__属性由now变成了wrapper(带参和不带参的都是wrapper)

所以需要把原始函数的__name__等属性复制到wrapper()函数中,否则依赖函数签名的代码执行就会发生出错

python内置的 functools.wraps 就是干这个事的。

在wrapper的定义前面加上

@functools.wraps(func)
即可。

使用functools需要先import functools模块

完整的不带参数的装饰器代码如下:

import functoolsdef log(func):    @functools.wraps(func)    def wrapper(*args, **kw):        print 'call %s(): ' % func.__name__        return func(*args, **kw)    return wrapper@logdef now():    print '2017-07-19'now()print now.__name__
运行结果如下:

call now(): 2017-07-19now


以上两个例子被装饰的函数都是带参数的,如果被装饰的函数不带参数,则可以减少一层嵌套

如不带参的装饰器可以简化为:

def log(func):    print 'decorator'    return func@logdef func():    print 'Im func.'func()


内置的三个装饰器:

staticmethod :静态方法,可以通过类或类的对象来调用,不会隐式传入任何参数

classmethod:类方法,和一个class相关的方法,可以通过类或类的对象来调用,并将该class隐式地当做第一个参数cls

property:对类属性的操作,类似于java的setter/getter

class B():    def __init__(self):        self.__prop = 1    @property    def prop(self):        print "call get"        return self.__prop    @prop.setter    def prop(self, value):        print "call set"        self.__prop = value    @prop.deleter    def prop(self):        print "call del"        del self.__prop
上面是一个property的使用例子,暂不深入理解。