python基础17-闭包函数-无参装饰器

今日学习

闭包函数简介

闭包函数的实际应用

装饰器简介

装饰器推导流程(重要)

装饰器功能完善

装饰器统一使用模板(通用)

装饰器语法糖

装饰器修复计数(待补充)

闭包函数概念

1.定义在函数内部的函数

2.内部函数使用了外部函数名称空间的名字

ps:只有符合上述两个特征的函数才能称为闭包函数
---------------------------
def warapper(username):               #定义warapper函数 username是形参
    #username = 'jason'      
    def index():
        print(username)
    return index

res()

闭包函数的实际应用

import requests
 
#方式一:
def get(url):
    return requests.get(url).text
 
#方式二:
def page(url):                1. #url为形参,page(https:xx实参)相
    def get():                2. #还未调用不看。
        return requests.get(url).text       3. #get获取(url)形参位
    return get                   4.#返回get

# 方式一下载同一页面
get('https://www.python.org')
get('https://www.python.org')
get('https://www.python.org')
……
 
# 方式二下载同一页面
python=page('https://www.python.org')      #将page('https://www.python.org')传给python
python()
python()
python()
……

装饰器

可以理解为:闭包+函数对象+嵌套

在不改变被装饰对象原来的调用方式内部代码的情况下,给被装饰对象添加新的功能

  • 装饰器推导

    -------------------------问题运行代码块并打印出代码块运行时间--------------------------
    # 改变了代码冗余问题(函数传参)
    import time
    #
    # 需求,打印
    # #函数传参 案例一
    # def index(x, y):
    #
    #     start = time.time()
    #     time.sleep(3)
    #     print('index %s %s' % (x, y))
    #     stop = time.time()
    #     print(stop - start)
    # index(111,222)
    #但是需求一次,我们就要做一次print打印,代码冗余繁琐。将print和time优化成函数体
    ------------------------------------------------------------
    
    # #函数传参 方案二
     def index(x,y):
          time.sleep(3)
          print('index %s %s' % (x, y))
     def wrapper():
         start = time.time()
         index(1111, 2222,111) #太死板,如果有改变的话,代码会冗余,位置实参不填写正确也会报错。
         stop = time.time()
         print(stop - start)
     wrapper()
    #此时我们将index(1111, 2222,111)打印需求修改,还有改代码。
    ----------------------------------------------------------------------------
     方案3:方案三优化一  将index(x,y)传参,设置wrapper
    
    # 函数传参
     def index(x,y):
          time.sleep(3)
          print('index %s %s %s' % (x, y))
     def wrapper(g,z):
         start = time.time()
         index(g,z)
         stop = time.time()
         print(stop - start)
    # 打印
     wrapper(111,2223)
        
    -----------------------------------------------------------------------------------
    # 方案3优化二 优化wrapper函数,将index方案写活了
    
     def index(x,y,z):
          time.sleep(2)
          print('index %s %s %s' % (x, y, z))
    
     def wrapper(*args,**kwargs):
         start = time.time()
         index(*args,**kwargs)      #warapper  灵活了,但是index比较死板,如果是再新增home功能,
         stop = time.time()          # 还要再多写一遍函数体,所以尽可能的把index给做成变量。
         print(stop - start)
     wrapper(111,2223,33333)
    -----------------------------------------------------------------------------------
    
    # 方案3优化三#除了将设置warapper函数体后,将函数体内的index优化为传参。
    def index(x, y, z):
        time.sleep(2)
        print('index %s %s %s' % (x, y, z))
    	print(index)
    
    def outer(func):
        def wrapper(*args, **kwargs):
            start = time.time()
            func(*args, **kwargs)  # func实参成为了index,(*args,**kwargs)变为(x,y,z)
            stop = time.time()
            print(stop - start)
        return wrapper
    
    index = outer(index)      #新定义index变量
    index(11,22,33)         
    # func(11,22,33)
    # 1.将index函数 赋值传给上面函数体中的func形参中,此时outer函数形参传给内层函数体(wrapper)下的func
    
  • 推导总结

    1.统计某个函数的运行时间
    2.将统计函数运行时间的代码封装成了函数
    3.直接封装成函数会改变调用方式
    4.利用闭包函数传参尝试
    5.利用重名替换原来函数名的功能
    6.函数的参数
    7.函数的返回值装饰器各种版本
    
  • 装饰器各个版本

    import time
    def home():
        time.sleep(2)
        print('from home')
        return '执行home函数之后的返回值' 
    
    """针对有参无参函数如何兼容"""
    def outer(xxx):
        def get_time(*args, **kwargs):
            start_time = time.time()  
            res = xxx(*args, **kwargs)  
            end_time = time.time()
            print('函数的执行时间是:', end_time - start_time)
            return res
        return get_time
    
    # @outer#装饰语法糖  #home = outer(home)
    home = outer(home)        #outer(home)将home传参给outer(xxx)
    xxx = home()
    print(xxx)
    
    ------------------执行结果--------------------------------
    from home
    函数的执行时间是: 2.008957624435425
    执行home函数之后的返回值
    
    ----------------装饰器叙述总结----------------------
    1.首先定义了home代码功能块,然后outer为无参装饰器(可以理解为嵌套函数outer(xxx)函数体);
    
    2.因为xxx为形参位,outer(home) 就是home作为实参传入xxx形参中。
    3. 闭包函数内层中res = xxx(*args, **kwargs)  相当于 res = home()
    4.res变量 返回结果给get_time
    5.get_time函数返回结果
    6.定义一个新的home变量 home = outer(home)
    7.home()调用
    

拓展小知识-return

  • def add(x, y):
        z = x + y
        return  z
    # print(add(x, y))       #不加return  返回none
    print(add(1,2))  
    -----结果------
    3
    --------------------
    return返回值只能通过print打印才会显示出来,但在交互式模式下不需要print打印-------
    return的作用之一是返回计算的值
    
  • 固定模板

    ---------------- 使用方法  模板 +@outer+代码块-------------------
    
    from functools import wraps               #装饰器的修复技术
    def outer(func_name):
        @wraps(func_name)  # 仅仅是为了让装饰器不容易被别人发现 做到真正的以假乱真
        def inner(*args, **kwargs):
            print('执行被装饰对象之前可以做的额外操作')
            res = func_name(*args, **kwargs)
            print('执行被装饰对象之后可以做的额外操作')
            return res
        return inner
    
    
    
  • 装饰器语法糖

    # 装饰器语法糖
    import time
    
    @outer  #  home = outer(真正的函数名home)
    def home():
        '''我是home函数 我要热死了!!!'''
        time.sleep(1)
        print('from home')
        return 'home返回值'
    
    # help(home)
    # print(home)
    home()
    
    # def index():
    #     '我是index函数 我的功能很强大'
    #     pass
    #
    # help(index)
    
posted @ 2022-07-06 21:59  名字长的像一只老山羊  阅读(27)  评论(0编辑  收藏  举报