• python中的装饰器


    原理:开头总要先说几句废话

    装饰器是一种对闭包的使用方式。通过查看它的 func_closure 属性可以看出函数闭包特性。
    真正理解装饰器有这么几个东西一定要透彻理解:

    1. 变量作用域LEGB
    2. 函数是顶级对象

    开始升级

    level 1:有用没用,先搞它出来一个

    def decorator(fn):
        def inner(n):
            return fn(n) + 1
        return inner
    
    # the "@" statement is same as f = decorator(f)
    @decorator
    def f(n):
        return n + 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    level 2: 使用装饰器,帅气的输出信息

    def wrap_with_prints(fn):
        # This will only happen when a function decorated
        # with @wrap_with_prints is defined
        print('print this when you decorate a function')
        def wrapped():
            # This will happen each time just before
            # the decorated function is called
            print('prepare to run %s' % fn.__name__)
            # Here is where the wrapper calls the decorated function
            fn()
            # This will happen each time just after
            # the decorated function is called
            print('done running %s' % fn.__name__)
    
        return wrapped
    
    @wrap_with_prints
    def func_to_decorate():
        print('some be wrapped')
    
    func_to_decorate()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    level 3 : 哎呀被装饰的函数参数不一样我可怎么办呀

    def log_calls(fn):
        ''' Wraps fn in a function named "inner" that writes
        the arguments and return value to logfile.log '''
        def inner(*args, **kwargs):
            # Call the function with the received arguments and
            # keyword arguments, storing the return value
    
            out = fn(*args, **kwargs)
    
            # Write a line with the function name, its
            # arguments, and its return value to the log file
            print('{} called with args {} and kwargs {}, returning {}\n'.format(fn.__name__,  args, kwargs, out))
    
            # Return the return value
            return out
        return inner
    
    @log_calls
    def add(a,b):
        return a+b
    add(1,2)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    level 4:装饰一个还不够,要装饰两次才最好

    装饰器可以链式使用,但是一定要注意使用顺序

    def b(fn):
        return lambda s: '{}'.format(fn(s))
    
    def em(fn):
        return lambda s: '{}'.format(fn(s))
    
    @b
    @em
    def greet(name):
        return('Hello, {}!'.format(name))
    
    print(greet("zyt"))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    level 5:装饰器也想要个属于人家自己的小参数嘛~

    def add_log_out(log_level):
        def wrapper(f):
            def return_f(*real_para):
                """inner doc
                """
                print("[{}]: {} with parameter {}".format(log_level, f.__name__, real_para))
                return f(*real_para)
    
            return return_f
        return wrapper
    
    # same as "add = add_log_out("INFO")(add)"
    @add_log_out("INFO")
    def add(a,b):
        """return a + b
        """
        return a+b
    
    print(add(1,2))
    print(add.__name__)
    print(add.__doc__)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    level 6:男人有了钱会变坏,函数有了装饰器却不会

    from functools import wraps
    def add_log_out(log_level):
        def wrapper(f):
            @wraps(f)
            def return_f(*real_para):
                """inner doc
                """
                print("[{}]: {} with parameter {}".format(log_level, f.__name__, real_para))
                return f(*real_para)
    
            return return_f
        return wrapper
    
    # same as "add = add_log_out("INFO")(add)"
    @add_log_out("INFO")
    def add(a,b):
        """return a + b
        """
        return a+b
    
    print(add(1,2))
    print(add.__name__)
    print(add.__doc__)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    参考:

    1. Python Decorators Overview
    2. 简单 12 步理解 Python 装饰器
  • 相关阅读:
    c语言socket ipv4服务端
    .bat批处理命令处理文件
    .NET餐厅管理系统sql数据帮助类执行单条SQL(插入、更新、删除)
    三维模型相机视角投影详细介绍及python程序解析
    绩效只是绩效
    【美团3.18校招真题2】
    13.罗马数字转整数
    校招笔试一直跪?那你会骗分吗?
    2023 10月最新Vmd 下载安装教程,Windows&Linux
    vue-在组件中使用v-model
  • 原文地址:https://blog.csdn.net/cookieZZ/article/details/127698765