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

    0.1高阶函数

    def sort(iterable,reverse=False,key=lambda x,y:x<y):
        lst = []
        for x in iterable:
            for k,v in enumerate(lst):
                if reverse:
                    flag=key(x,v)
                else:
                    flag= not key(x,v)
                if flag:
                    lst.insert(k,x)
                    break
            else:
                lst.append(x)
        return lst
    sort([2,5,6,1,4],reverse=True,key = lambda x,y:x>y)

    1.1currying
    指的是将原来接受两个参数的函数变成新的接受一个参数的函数的过程。新的函数返回一个以原有第 二个参数为参数的函数

    def add(x,y):
    return x+y
    print(add(4,5)) 转换成
    def add(x): def _add(y): return x+y return _add print(add(5)(6))

    1.2装饰器的演变

    #业务功能分离,fn函数调用传参是个问题
    def add(x,y):
        return x+y
    def logger(fn):
        print('begin')
        x = fn(4,5)
        print('end')
        return x
    print(logger(add))

    解决了传参问题,进一步修改函数

    def add(x,y):
        return x+y
    def logger(fn,*args,**kwargs):
        print('begin')
        x = fn(*args,**kwargs)
        print('end')
        return x 
    print(logger(add,5,5))

    currying,改变函数调用的方式

    #currying
    def add(x,y):
        return x+y
    def logger(fn):
        def _logger(*args,**kwargs): #*args传参组成元祖,**kwargs传参组成字典
            print('begin')
            x = fn(*args,**kwargs) #*args,**kwargs是参数解构,此处fn调用了外层函数的参数fn是闭包 ;;add
            print('end')
            return x
        return _logger
    f = logger(add) #logger(add) 函数add已经传递进来给fn使用,左边重新赋值覆盖了add函数,引用计数后gc不垃圾回收
    print(f(5,6))
    f = logger(add)(5,6)  #currying的调用方式,;logger(add)外层函数return 内层函数wrapper
    print(f)
    add = logger(add)
    add(5,4)  #这个add调用的已经不是add函数了 而是增强版的add带装饰器的add
    logger(add)(4,5)  #等价于 add = logger(add)  -->add(4,5)

    装饰器语法糖

    def logger(fn):
        def wrapper(*args,**kwargs):
            x = fn (*args,**kwargs)
            return x 
        return wrapper
    @logger  #等价于 add = logger(add)
    def add(x,y):  #由于add = logger(add)-->这里的add已经不是函数定义了 而是logger返回的return wrapper
        return x+y  #return x+y 把返回值,传递给fn并且赋值给x,装饰器return x

    1.3装饰器的副作用,以及带参数的装饰器

    def copy_properties(src,dst):
        dst.__name__ = src.__name__
        dst.__doc__ = src.__doc__
    
    def logger(fn):
        def wrapper(*args,**kwargs):
            """I am wrapper"""
            x = fn(*args,**kwargs)
            return x
        copy_properties(fn,wrapper)
        return wrapper
    @logger
    def add(x,y):
        """This is function for add """
        return x+y
    print("name={},doc={}".format(add.__name__,add.__doc__))
    #备注参数wrapper.__name__=fn.__name__  ;fn的name属性是正常的 传递给wrapper的name属性
    更改后
    def copy_properties(src):
        def _copy_properties(dst):
            dst.__name__ = src.__name__
            dst.__doc__ = src.__doc__
            return dst
        return _copy_properties
    
    def logger(fn):
        @copy_properties(fn) #wrapper = copy_properties(fn)(wrapper)
        def wrapper(*args,**kwargs):
            """I am wrapper"""
            x = fn(*args,**kwargs)
            return x
        return wrapper
    @logger
    def add(x,y):
        """This is function for add """
        return x+y
    print("name={},doc={}".format(add.__name__,add.__doc__))

    带参数的装饰器

    #带参数的装饰器
    import datetime
    def logger(duration):
        def _logger(fn):
            def wrapper(*args,**kwargs):  #被装饰函数需要传递参数的时候,需要装饰器里面添加*args,*kwargs;没有warpper也是带参数的装饰器
                start = datetime.datetime.now()
                print('begin')
                x = fn(*args,**kwargs)
                end = datetime.datetime.now()
                print('too fast') if (end-start).total_seconds()<duration else print('too slow')    
                print('end')
                return x
            return wrapper
        return _logger
    @logger(5)
    def add(x,y):
        time.sleep(2)
        return x+y
    add(5,6)
    本文为原创文章,转载请标明出处
  • 相关阅读:
    Python datetime time 等时间 日期 之间的计算和相互转化
    微信浏览器的html5页面显示配置等问题汇集 1,禁止微信浏览器分享页面链接 (定点更新)
    《Monitoring and Tuning the Linux Networking Stack: Receiving Data》翻译
    kubernetes安全认证相关资料
    ovn-architecture 摘要
    apt-get tips
    CNI插件编写框架分析
    ovn-kubernetes安装指南
    ovn-kubernetes执行流程概述
    《OVN Logical Flows and ovn-trace》翻译
  • 原文地址:https://www.cnblogs.com/harden13/p/8874553.html
Copyright © 2011-2022 走看看