首页 > 代码库 > python学习-装饰器

python学习-装饰器

参考: 

http://www.wklken.me/posts/2013/07/19/python-translate-decorator.html

http://www.cnblogs.com/wupeiqi/articles/4980620.html

一、装饰器必备知识

1、函数可以被赋值给一个变量

def show(msg):    print(msg)# 调用 show 函数show("这是调用 show() 的输出")# 将函数 show 赋值给 foofoo = show# 调用 foofoo("这是调用 foo() 的输出")# 删除 f1 函数后再次调用 f2del showfoo("这是删除 show() 之后条用 foo() 的输出")###########输出结果这是调用 show() 的输出这是调用 foo() 的输出这是删除 show() 之后条用 foo() 的输出

2、函数可以被重新定义

def show():    print("第一次定义 show")def show():    print("第二次定义 show")# 函数的输出会是:第二次定义 showshow()

3、函数的函数体里面也可以再定义函数,并且在函数体里面可以立即被调用

def show():    def foo():        return "WenChong"    print(foo())

4、函数的返回结果也可以是函数

def run(action=remove):    def remove_user():        return "del user name"    def add_user():        return "add user name"    if action == remove:        return remove_user    else:        return add_user# 将 run() 函数的返回值赋值给 actionaction = run(action=add)# 输出 action 的值会是一个函数对象print(action)# 在 action 后面加上 () ,会将 add_user()  函数的返回值输出print(action())# 也可以直接这样输出print(run(action=add)())#######输出结果<function run.<locals>.add_user at 0x10ce16840>add user nameadd user name

5、函数也可以作为一个参数传递给函数

def show():    return "WenChong"def foo(func):    msg = func()    print(msg)# 将函数 show 作为变量传递给 foo 函数foo(show)#######输出结果WenChong

6、动态参数

def my_func(*args,**kwargs):    print(args,kwargs)

二、写一个装饰器

装饰器是以另一个函数作为参数的函数

def func_action(my_func):    # 定义个一个 inner_func 函数,用户在 my_func 函数执行前后再执行其他代码    def inner_func():        print("my_func start...")        # 调用 my_func 函数,记得后面一定要有()        my_func()        print("my_func end...")    # 返回 inner_func 函数,这个函数里面包含了 my_func 函数的代码以及 my_func 前后的代码    return inner_func# 创建一个函数def my_func():    print("my_func 函数被调用")# 调用 my_func 函数my_func()######输出结果my_func 函数被调用

func_aciton 函数可以传递一个函数作为参数,并在这个参数的前后增加代码

那么就可以将 my_func 函数传递给 func_aciton 以完成对 my_func 的装饰

# 将 func_action 在赋值给一个变量 other_my_funcother_my_func = func_action(my_func)# 调用 other_my_func 函数other_my_func()######输出结果my_func start...my_func 函数被调用my_func end...

这样每次每次想在某个函数的前后增加代码的时候都可以通过 func_aciton 重新赋值给另外一个变量,并执行。

三、使用装饰器

通过上面的例子使用装饰器过于麻烦,需要定义另一个变量,然后再调用这个变量,python 提供了特殊的语法,在函数的上面使用 @func_action 添加装饰器

@func_actiondef my_func():    print("my_func 函数被调用")# 调用 my_func 函数my_func()#####输出结果my_func start...my_func 函数被调用my_func end...

@ 符号的作用:

1、将@符号下面的函数作为参数传递给@符号后面的函数,并执行

2、将返回的结果再重新赋值给@符号下面的函数

四、向装饰器函数传递参数以及获取返回值

当被装饰的函数有参数时,可以通过动态参数的方式来给被装饰的参数传递参数

当被装饰的函数有返回值时,可以通过捕获 func 的返回值通过 inner_func 返回

def func_action(func):    # 传递参数给别装饰的函数    def inner_func(*args,**kwargs):        print("func start...")        # 获取被装饰函数的返回值        ret =  func(*args,**kwargs)        print("func end...")        # 将被装饰函数的返回值返回给 inner_func        return ret    return inner_func

五、向装饰器传递参数

装饰器是一个以函数为参数的函数,那么如果需要向装饰器传递参数时,需要声明一个用于创建装饰的函数

# 声明创建装饰器的函数def decorator_maker(msg1,msg2):    print("decorator start make...",msg1)    # 真正的装饰器    def my_decorator(func):        def inner(*args,**kwargs):            print(func run start...)            ret = func(*args,**kwargs)            print(func run end...)            return ret        return inner    print("decorator end make...",msg2)    return my_decorator@decorator_maker(Wen,Chong)def show(msg):    print(msg)    return msg# 调用被装饰过后的函数 show(aaaa)

输出结果:

decorator start make... Wendecorator end make... Chongfunc run start...aaaafunc run end...

一个可以处理任何参数的装饰器代码片段

# 装饰 装饰器 的装饰器 (好绕.....)def decorator_with_args(decorator_to_enhance):    """     这个函数将作为装饰器使用    它必须装饰另一个函数    它将允许任何接收任意数量参数的装饰器    方便你每次查询如何实现    """    # 同样的技巧传递参数    def decorator_maker(*args, **kwargs):        # 创建一个只接收函数的装饰器        # 但是这里保存了从创建者传递过来的的参数        def decorator_wrapper(func):            # 我们返回原始装饰器的结果            # 这是一个普通的函数,返回值是另一个函数            # 陷阱:装饰器必须有这个特殊的签名,否则不会生效            return decorator_to_enhance(func, *args, **kwargs)        return decorator_wrapper    return decorator_maker

 

python学习-装饰器