zoukankan      html  css  js  c++  java
  • 装饰器

    参考: 

    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
  • 相关阅读:
    POJ 3259 Wormholes【BellmanFord】
    POJ 2960 SNim【SG函数的应用】
    ZOJ 3578 Matrixdp水题
    HDU 2897 邂逅明下【bash博弈】
    BellmanFord 算法及其优化【转】
    【转】几个Java的网络爬虫
    thinkphp 反字符 去标签 自动加点 去换行 截取字符串 冰糖
    php 二维数组转 json文本 (jquery datagrid 数据格式) 冰糖
    PHP 汉字转拼音(首拼音,所有拼音) 冰糖
    设为首页与加入收藏 兼容firefox 冰糖
  • 原文地址:https://www.cnblogs.com/wenchong/p/5827717.html
Copyright © 2011-2022 走看看