python 装饰器理解与使用

来源:互联网 发布:卖家如何弄淘宝返现 编辑:程序博客网 时间:2024/05/29 05:05

函数装饰器在python中属于比较高级但是却实用并且常用的技术。常见的使用场景比如 要在类里面实现一个静态方法
则需要使用@staticmethod装饰器,类方法@classmethod则需要这个装饰器。
函数装饰器有两种使用方式,一种是带参数的,一种是不带参数的

先说第一种不带参数的装饰器使用方式

#-*- coding:utf-8 -*-def dec(fun):    print u"我是dec装饰器函数"    return fun@decdef func():    print u"我是func函数"func()

以上代码输出如下

我是dec装饰器函数我是func函数

以上是不带参数的装饰器使用方式
使用python分为两步 一是定义一个装饰器 二是将装饰器函数应用到函数上面
先说装饰器的定义
在python 一个装饰器可以使任意一个能够返回一个可调用对象的可调用对象
并且装饰器的第一个参数是当前被装饰的函数的引用 在此例中dec(fun) 这个参数即是对func函数的引用
learning python 的原话是这样说

In fact, decorators can be any type of callable and return any type of callable:

也就是说 一:装饰器本身是一个可调用的对象 二:装饰器必须返回一个可以调用的对象
先说一:

   饰器本身是一个可调用的对象

这句话意思是说装饰器本身必须是可调用的,比如说函数是一个可以调用的对象 所以可以用函数来做装饰器
但是也不一定必须是一个函数 比如一个实现了call方法的类对象也是一个可调用的对象也可以用一个实现了
call方法的类对象来做装饰器比如以下形式

#-*- coding:utf-8 -*-class dec:    def __call__(slef,fun):        print u"我是类对象装饰器"        return fun@dec()def func():    print u"我是func函数"func()

以上代码输出如下

我是类对象装饰器我是func函数

再说二:
意思是说一个函数装饰器必须要返回一个可调用对象来替代被装饰的可函数,和第一条类似 返回的可以是一个函数也可其他可调用对象

#-*- coding:utf-8 -*-def dec(fun):    print u"我是dec装饰器函数"    def rf():        print(u"我是装饰器自定义的函数")    return rf@decdef func():    print u"我是func函数"func()

输出

我是dec装饰器函数我是装饰器自定义的函数

在之前的例子中我们之间返回的是被装饰的函数的引用,而在此处返回的是一个在装饰器里面定义的一个函数,这样就导致了原始函数被装饰器定义
的函数所取代

下面讨论装饰器的生效时间 当一个函数应用了一个装饰器的时候,当python运行到函数定义处时 也就是说装饰器在生成函数对象时就开始执行了
装饰行为看下面的代码

#-*- coding:utf-8 -*-def dec(fun):    print u"我是dec装饰器函数"    def rf():        print(u"我是装饰器自定义的函数")    return rf@decdef func():    print u"我是func函数"

输出

我是dec装饰器函数

上面的代码中并没有调用func函数 但是依然有输出 说明函数装饰器是在函数对象生成时就已经开始执行

再说带参数的函数装饰器
装饰器也可以带参数

#-*- coding:utf-8 -*-def dec(arg):    print u"我是带参数装饰器函数 -- 参数为%s" % arg    def rf(fun):        print(u"我是装饰器自定义的函数")        return fun    return rf@dec('arg_1')def func():    print u"我是func函数"func()

输出

我是带参数装饰器函数 -- 参数为arg_1我是装饰器自定义的函数我是func函数

注意装饰器的定义方式与之前定义方式的不同

装饰器嵌套

#-*- coding:utf-8 -*-def dec(fun):    print "in dec -- %s" % fun    def y():        pass    return ydef dec1(fun):    print "in dec1 -- %s" % fun    def f():        print "i'm in dec1 ***"        pass    return f@dec1@decdef func():    print u"我是func函数"print funcfunc()

输出

in dec -- <function func at 0x028FDA30>in dec1 -- <function y at 0x028FDA70><function f at 0x028FDA30>i'm in dec1 ***

有以上输出顺序可知 python首先执行dec装饰器
并将func引用传入给dec 而dec返回的是内部定义的函数y
此后执行dec1装饰器 并经dec返回的函数y最为参数传给dec1
然后 dec1返回函数f 作为最终装饰结果
所以 调用函数func() 相当于调用dec1中的f()函数

0 0
原创粉丝点击