• python 装饰器


    需求:

    一个加法函数,想增强它的功能,能够输出加法函数的日志信息

    def add(x, y):
        return x + y

    增加信息输出功能:

    def add(x, y):
        print("call add,x + y") #日志输出到控制台
        return x + y

    上面的加法函数是完成了需求,但是有以下的缺点:

      打印日志信息是一个功能,这条语句和 add 函数耦合太高;

      加法函数属于业务功能,而输出日志信息的功能,属于非业务功能代码,不该放在业务函数 add 中;

    下面代码做到了业务功能分离,但是 fn 函数调用传参是个问题:

    def add(x, y):
        return x + y
    
    def logger(fn):
        print('before')
        print('add function:{} {}'.format(4, 5))
        ret = fn(4, 5)
        print('after')
        return ret
    
    print(logger(add))

    解决了传参的问题,进一步改变:

    def add(x, y):
        return x + y
    
    def logger(fn, *args, **kwargs):
        print('before')
        print('add function:{} | {}'.format(args, kwargs))
        ret = fn(*args, **kwargs)    # 参数解构
        print('after')
        return ret
    
    print(logger(add, 4, 5))
    print(logger(add, x=4, y=6))
    print(logger(add, 4, y=15))

    柯里化:

    def add(x, y):
        return x + y
    
    def logger(fn):
        def wrapper(*args, **kwargs):
            print('before')
            print('add function:{} | {}'.format(args, kwargs))
            ret = fn(*args, **kwargs)    # 参数解构
            print('after')
            return ret
        return wrapper
    
    print(logger(add)(4, 5))
    # 换一种写法:
    '''
    add = logger(add)
    print(add(x=5, y=10))
    '''
    # 1.先算等式右边,logger(add)
    # 2.add函数对象被fn记住
    # 3.logger函数返回 wrapper,即add = wrapper
    # 4.调用add(4, 5)即wrapper(4, 5)
    # 5.ret = fn(*args, **kwargs),此处的fn记住的是最原始的add函数对象

    装饰器语法糖:

    def logger(fn):
        def wrapper(*args, **kwargs):
            print('before')
            print('add function:{} | {}'.format(args, kwargs))
            ret = fn(*args, **kwargs)    # 参数解构
            print('after')
            return ret
        return wrapper
    
    @logger    # 等价于add = logger(add)
    def add(x, y):
        return x + y
    
    print(add(20, 30))
    '''
    可以采用逆推思维:
    1.add(20, 30)
    2.包装add(20, 30)为:wrapper(20, 30)
    3.实现日志增强功能:logger(add)(20, 30)
    即:add(20, 30) => wrapper(20, 30) => logger(add)(20, 30)
    
    def logger(fn):
        def wrapper(*args, **kwargs):
            val = fn(*args, **kwargs)
            return val
        return wrapper
    @logger
    def add(x, y):
        return x + y
    '''

    @logger是什么?这就是装饰器语法

    装饰器(无参)

      它是一个函数

      函数作为它的形参,无参装饰器实际上就是一个单形参函数

      返回值也是一个函数 可以使用 @functionname 方式,简化调用

      注:此处装饰器的定义只是就目前所学的总结,并不准确,只是方便理解

    装饰器和高阶函数

      装饰器可以是高阶函数,但装饰器是对传入函数的功能的装饰(功能增强)

  • 相关阅读:
    pyCharm报错"your evaluation license has expired, pycharm will now exit"解决方法(实测)
    (转)python selenium-webdriver 元素操作之鼠标和键盘事件
    转载:PICT使用教程(设计测试用例工具)
    转载:小米电视怎么安装爱奇艺
    关于VMware 15搭建MacOS 10.14后无法播放在线视频和客户端视频的问题
    Reference resources
    centos7 启用iptables
    disabling IPv6 name/address support: Address family not supported by protocol
    rngd.service 启动失败的处理
    mdadm Raid5 /dev/md0 lost a disk and recovery from another machine
  • 原文地址:https://www.cnblogs.com/zyybky/p/12918913.html
Copyright © 2020-2023  润新知