Python中如何在一个函数中加入多个装饰器?

示例:

def makebold(fn):
    def wrapped():
        return "<b>" + fn() + "</b>"
    return wrapped

def makeitalic(fn):
    def wrapped():
        return "<i>" + fn() + "</i>"
    return wrapped

@makebold
@makeitalic
def hello():
    return "hello world"

print hello() ## returns <b><i>hello world</i></b>

装饰器基础

  • Python 中的函数都是对象

  • 你可以在一个函数里定义另一个函数

这意味着函数可以返回另一个函数

自己动手实现装饰器

@decorator 就是下面的简写:

装饰器高级用法

在装饰器函数里传入参数

装饰方法

在 Python 里面方法和函数几乎一模一样,唯一的区别就是方法的第一个参数是一个当前对象的 self。

如果想造一个更加通用的,可以同时满足方法和函数的装饰器,用 *args,**kwargs 即可

把参数传递给装饰器

装饰器必须接收一个函数当做参数,所以不可以直接把被装饰函数的参数传递给装饰器

装饰器就是一个平常的函数,不用 @ 也可以直接调用。当使用 @my_decorator 只是告诉 Python 去调用被变量 my_decorator 标记的函数

一个 DEMO

需要记住的是,装饰器只能被调用一次,当 Python 载入脚本后,不可以动态地设置参数了。即运行了 import x 之后,函数已经被装饰了

于是弄一个通用的装饰器,只要装饰了这个装饰器,自定义的装饰器就可以接收任意的参数了

删除多余注释:

使用方法:

之后调用这个自定义的装饰器,就可以传递任意参数了:

自己成功使用的示例:

后续

  • 装饰器是 Python2.4 里面引进的,所以确保 Python 解释器的版本 >= 2.4

  • 装饰器使函数调用变慢了

  • 装饰器不能被取消

  • 用装饰器装饰函数,可能会导致 DEBUG 难度变高

functools 模块

functools.wraps() 函数,可以复制装饰器的名字、模块和文档给它的包装器【PS:functools.wraps() 本身就是一个装饰器】

装饰器的用途

传统的用法就是用它来为外部的库函数(你不能修改的)做扩展或者 DEBUG(你不想修改的)

Python 自身提供了几个装饰器,像 propertystaticmethod

  • Django 用装饰器管理缓存和视图的权限

  • Twisted 用来修改异步函数的调用

Last updated

Was this helpful?