• 装饰器


    参考: 

    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 赋值给 foo
    foo = show
    
    # 调用 foo
    foo("这是调用 foo() 的输出")
    
    # 删除 f1 函数后再次调用 f2
    del show
    foo("这是删除 show() 之后条用 foo() 的输出")
    
    ###########输出结果
    这是调用 show() 的输出
    这是调用 foo() 的输出
    这是删除 show() 之后条用 foo() 的输出

    2、函数可以被重新定义

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

    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() 函数的返回值赋值给 action
    action = run(action='add')
    
    # 输出 action 的值会是一个函数对象
    print(action)
    
    # 在 action 后面加上 () ,会将 add_user()  函数的返回值输出
    print(action())
    
    # 也可以直接这样输出
    print(run(action='add')())
    
    
    #######输出结果
    <function run.<locals>.add_user at 0x10ce16840>
    add user name
    add 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_func
    other_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_action
    def 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... Wen
    decorator end make... Chong
    func run start...
    aaaa
    func 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
  • 相关阅读:
    微信小程序-rpx
    vue项目页面切换到默认显示顶部
    访问formData的数据
    vue图片懒加载
    react+umi+dva
    switch判断中,case后面跟逻辑表达式出错
    给2020做一个小结
    react+next.js遇到的问题及解决
    域名相关(结构与规范)
    react+antd一边踩坑一边积累
  • 原文地址:https://www.cnblogs.com/wenchong/p/5827717.html
Copyright © 2020-2023  润新知