理解Python函数装饰器

来源:互联网 发布:手机收银软件免费版 编辑:程序博客网 时间:2024/05/16 10:39

理解Python函数装饰器

Python中的函数装饰器是一种能在不修改函数及函数名的前提下给函数添加额外功能的写法.

我说装饰器是种写法, 是因为装饰器其实并不是什么不同的语法, 而是一种解决某类问题的一种写法. 即使你不知道装饰器, 可能在解决一些问题的时候也写出了装饰器.

问题场景

我们有一个函数:

def func_a(x):    print x*x    a(2)

现在想在print前显示时间time.time(), 最简单的写法是直接加上这一句:

import timedef func_a(x):    print time.time()    print x*x    a(2)

但是我们不想修改func_a的代码(实际场景可能是这个函数是别人写的, 或者函数逻辑很复杂, 不好直接修改),这时候可以通过其他函数调用来实现:

import timedef func_a(x):    print x*x    def func_a_plus(x):    print time.time()    return func_a(x)func_a_plus(2)

这时候有个问题了, 假设其他模块中大量调用了这个func_a, 我们想在不修改func_a名称的前提下给它加功能.

不能直接把func_a_plus赋值给func_a(会造成循环引用的问题), 可以把函数作为参数传递来实现:

import timedef func_a(x):    print x*x    def func_a_plus(func):    print time.time()    return funcfunc_a = func_a_plus(func_a)

解决方法似乎已经变得麻烦起来了. 更麻烦的是, 这种写法其实不符合要求, 因为新函数返回的其实还是未经改变的原函数, time.time()只在赋值时运行了一次, 之后就不会再运行.

所以, 只能把一个新函数赋值给原函数名, 又不能造成循环引用的问题, 如何实现?

答案是靠Python中的闭包. 在函数内部重新定义一个函数, 将内部嵌套的函数返回给原函数名, 这个函数名就会指向嵌套的函数.

import timedef func_a(x):    print x*xdef func_plus(func):    def wap(x):        print time.time()        return func(x)    return wapfunc_a = func_plus(func_a)

这个新函数func_plus就是装饰器了.

 语法糖

Python 中有个语法糖可以更方便地写装饰器:

import timedef func_plus(func):    def wap(x):        print time.time()        return func(x)    return wap@func_plusdef func_a(x):    print x*x@func_plusdef func_b(x):    print x*x*x

这种@装饰函数的写法代替了重新赋值的语句func_a = func_plus(func_a), 但实现的功能相同.

原创粉丝点击