zoukankan      html  css  js  c++  java
  • 闭包函数 装饰器

    闭包函数

      顾名思义就是定义在函数内部的函数,内部函数引用了外部函数作用域的名字

    def outter():
        x = 111
        def inner():
            print(x)
        return inner
    res = outter()  # res就是inner函数内存地址
    
    def func():
        x = 333
        res()
    func()  # 返回的还是111 # 因为在定义阶段就已经固定了
    # 补充:像inner这样虽然他的x调用的是全局的,
    # 但他的y引用了外部函数名称空间作用域的名字,
    # 且他是定义在函数内部的函数,
    # 所以依然是满足闭包函数的两点要求的,所以也是闭包函数
    x = 111 def outer(): y = 222 def inner(): print(x,y) return inner

    给函数体传参有两种方式

    1. 传参

      def index1(username):  # 这里的username就是变量名,也可以说是参数

      print(username)  # 这样就往函数体内传入了参数

    2. 闭包

    def outter(x,y):
        def my_max():
            if x > y:
                return x
            return y
        return my_max
    res1 = outter(1,40)  # res1就是my_max函数的内存地址
    print(res1())  # 40
    print(res1())  # 40
    res2 = outter(90,200)  # 这里的res2也是my_max函数的内存地址
                           # 虽然之前已经传了值了
                           # 但是在上一句代码执行结束后
                           # 关系解除,这里又建立了新的关系。
    print(res2())  # 200
    print(res2())  # 200
    print(res2())  # 200
                    

      需要注意传参和闭包的使用场景:

        1. 直接传参,可能会是在全局中定义,占用变量名,当项目较大,要传参数过多时,

          不推荐使用这个方法,只在小项目中可以使用。

        2. 闭包传参,特点是只给内部传参,在局部定义变量名,而不是全局,比较安全,起名也方便。

    装饰器

      就是用来装饰的工具,就是给被装饰的对象添加新的功能,并且不改变原来的使用方法。

      装饰器的使用要遵循开放封闭原则

        开放:对扩展开放

        封闭:对修改封闭

      装饰器(装饰器也是可调用对象callable=True)必须遵循的两个原则:

        1. 不改变被装饰对象源代码

        2. 不改变被装饰对象(必须是可调用对象)调用方式

    补充:

      # 统计函数运行时间的方法

      1.
      import time

      print(time.time())

       # 返回的是 时间戳 即当前时间距离1970-1-1 00:00:00相差的秒数 

      2.

      time.sleep(3)

      #让程序暂停三秒再运行

    装饰器简单版本

      

    import time
    def index():
        time.sleep(3)
        print('过了三秒,我开始执行了')
    
    def outter(func):  # func = 最原始的index函数的内存地址
        def get_time():
            start = time.time()
            func()  # func = index函数的内存地址() 直接调用
            end = time.time()
            print('index run time:%s'%(end-start))
        return get_time
    index = outter(index)  # outter(最原始的index函数内存地址)
    # index指向get_time函数的内存地址
    index()


    import time
    def index01():
    time.sleep(3)
    print('过了三秒,我开始执行了')

    def outter(func): # func = 最原始的index函数的内存地址
    def get_time():
    start = time.time()
    func() # func = index函数的内存地址() 直接调用
    end = time.time()
    print('index99 run time:%s'%(end-start))
    return get_time
    index99 = outter(index01) # outter(最原始的index函数内存地址)
    # index指向get_time函数的内存地址
    index99()

     装饰器语法糖

    会将紧挨着它的可调用对象的名字当做参数自动传入调用outter

      @outter      #  等价于outter(index)
      def index():
        pass

    无参装饰器

        from functools import wraps
        def outter(func):
            @wraps(func)
            def inner(*args,**kwargs):  # * **在形参中使用
                # 执行被装饰函数之前你可以做的操作
                res = func(*args,**kwargs)  # * **在实参中使用
                # 执行被装饰函数之后你可以做到操作
                return res
            return inner
    
        @outter
        def index(username,*args,**kwargs):
            """index注释"""
            pass
        print(index)
    ########## 补充-重要 ##########
     wraps方法
            # 有以下两个作用
            # 1.返回原来的函数的函数名
            # 2.返回原来的函数的注释
    
    使用方法就是
    首先调用
    from functools import wraps
    
    然后在最内层函数正上方
    加上 @wraps(func)

    有参装饰器(最复杂就三层)

    def wrappers(data):
        # data = 'file'
        def outter(func):
            def inner(*args,**kwargs):
                if data == 'file':
                    # 执行被装饰函数之前你可以做的操作
                    res = func(*args,**kwargs)  # * **在实参中使用
                    # 执行被装饰函数之后你可以做到操作
                    return res
            return inner
        return outter

    装饰器的嵌套

      1. 装饰的时候,从下往上

      2.执行的时候,从上往下

    @outter1  # index = outter1(func2)
    @outter2  # func2 = outter2(func1)
    @outter3  # func1 =  outter3(index)
    def index():
        pass
  • 相关阅读:
    【NLP之文本摘要】4_oov和word repetition问题
    【文本摘要项目】5性能提升之PGN模型
    案例学习Transformer 及其实现细节]
    【NLP之文本摘要】3NLG过程及其优化与模型评估
    案例学习理解语言的 Transformer 模型
    【文本摘要项目】4解码算法及模型测试结果评估
    【NLP之文本摘要】5_transformer模型初级探索
    【文本摘要项目】6性能提升之Transformer模型
    【文本摘要项目】7性能提升之基于Transformer的PGN模型
    指针作为参数传入函数的陷阱
  • 原文地址:https://www.cnblogs.com/PowerTips/p/11171777.html
Copyright © 2011-2022 走看看