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

    今日学习的内容:闭包函数、装饰器。

    闭包函数

    闭包函数就是两个函数的嵌套,两个函数分为内部函数和外部函数,当外部函数的返回值是内部函数的引用的时候,就构成了闭包的情况。

    def func():  # 外部函数
        name = 'jason' 
        def inner():  # 内部函数
            print(name)  # 内部函数的执行
        return inner  # 返回值为内部函数
    
    f = func()  # 外部函数引用了内部函数
    f()

     闭包函数要满足一下两点:

    1、定义在函数内部的函数。

    2、内部函数引用外部函数名称空间作用域的名字。

    要点:函数在定义阶段名字的查找顺序就已经固定死了,不会因为函数调用位置的变化而改变。

    给函数传参会用到的两种方式:
    1、直接传参
        def index(name):
              print(name)
    
    2、闭包
        def outter(name):
              name = 'jason'
              def index():
                    print(name)
              return index

     装饰器

    装饰器的作用是给被装饰的对象添加新的功能。

    装饰器的开放封闭原则:开放(对扩展开放)、封闭(对修改封闭)

    装饰器(调用对象)必须遵循的两个原则:

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

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

    #小知识点
    import time
    print(time.time())  # 时间戳,显示的是当前时间距离1970-1-1 00:00:00相差的秒数
    
    time sleep(3)  # 让你的程序暂停3秒再执行
    print('NB')

    我们先写一个函数

    import time
    def index():
        time.sleep(3)
        print('时间到了,gogogo!')
    print(index())

    我们要添加一个功能,用来统计index函数执行的时间

    start = time.time()  # 记录index开始的时间
    index()
    end = time.time()  # 记录index结束的时间
    print('index run time:%s'%(end-start))  # 打印出运行index()的时间

    我们把这个功能写到一个函数里面然后要让我们在直接调用index()的时候能加入这个

    import time
    def index():
        time.sleep(3)
        print('时间到了,go go go!')
    
    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函数内存地址),本质上返回了get_time
    # index指向get_time函数的内存地址
    index()  #本质上调用了get_time函数,get_time()中的func()才调用的是原函数

    我们通过命名了一个与index()同名的变量名达到了目地,接下来要让它的返回值也与index()相同。

    import time
    def index():
        time.sleep(3)
        print('时间到了,go go go!')
        return 'index'
    def outter(func):  # func = 最原始的index函数的内存地址
        def get_time(*args, **kwargs):  # args = ('egon',) kwargs = {}
            start = time.time()
            res = func(*args, **kwargs)  # 最原始的index函数的内存地址() 直接调用  
            end = time.time()
            print('func run time:%s'%(end-start))
            return res
        return get_time
    index=outter(index)  
    print(index())

    pychram中的语法糖

    @outter  # index = outter(index)  outter(最原始的index的函数的内存地址)
    def index():
        time.sleep(3)
        print('时间到了,go go go!') 
        return 'index'

    @outter就是语法糖,在@的后面就是你装饰器的最外层的函数名,然后语法糖会把紧挨着它的下面的函数名当做参数进行调用

    装饰器修复技术

    from functools import wraps
    def outter(func):
        @wraps(func)  # 装饰器修复技术,加载内层函数的正上方
        def inner(*args,**kwargs):

    在加入了装饰器修复技术后用户查看到的就是被装饰函数的本身,而且查看到的注释也是被装饰函数本身的注释。

    装饰器的模板

    1.无参装饰器
        from functools import wraps
        def outter(func):
            @wraps(func)
            def inner(*args,**kwargs):  # * **在形参中使用
                # 执行被装饰函数之前你可以做的操作
                res = func(*args,**kwargs)  # * **在实参中使用
                # 执行被装饰函数之后你可以做到操作
                return res
            return inner
    
    
    2.有参装饰器(最复杂就三层)
    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
  • 相关阅读:
    CF235D
    模拟赛 circle 题解
    平面图总结
    kd 树总结
    思维题
    luogu P1600 天天爱跑步
    UOJ #42. 【清华集训2014】Sum
    FZOJ 4344 连通性
    平衡树
    计蒜客 T3225 Darko 的生成树
  • 原文地址:https://www.cnblogs.com/wangnanfei/p/11173240.html
Copyright © 2011-2022 走看看