zoukankan      html  css  js  c++  java
  • 【python 第五日】 函数闭包与装饰器

    函数闭包:

      概念:函数内部嵌套函数,并且外部函数返回内部函数,嵌套函数用到外部函数的局部变量,嵌套函数+局部变量=闭包

    def a1():
        a=1
        def a2():
            nonlocal  a   #如果不加这一句,下一句会报错,说a未定义,但是如果下一句用b=a+1 这时候可以不用添加
            a = a + 1
            print(f"a2的a都是{a}")
        print(f"a1的a都是{a}")
        return a2
    
    x=a1()()
    
    输出如下:
    a1的a都是1
    a2的a都是2

    a2() 和a变量一起组成了闭包

    装饰器

    装饰器:本质就是函数,返回内部函数,内部函数有调用函数的接口,功能是为其他函数添加附加功能=高级函数+闭包+函数嵌套

    原则:

    1、不修改原函数的调用方式

    2、不修改原函数的源代码

     返回值问题:最后返回的是嵌套函数的返回值,不是原函数的返回值

    @timer 装饰器问题,即使没有test(),他也会运行

    #运行test() 相当于运行wrapper(),所以是wrapper的返回值
    
    import time
    def timer(func):
    def wrapper(*args, **kwargs):
    start_time= time.time()
    print("wrapper开始了。")
    # f_res = func(*args, **kwargs) # 如果运行注释的函数,这样可以返回原函数的返回值
    func(*args, **kwargs)
    end_time= time.time()
    print("wrapper结束: 共用时间:%d秒" %(end_time - start_time))
    return "这是wrapper的返回值"
    # return f_res
    return wrapper

    @timer #相当于test = timer(test) ####这一步编译的时候就运行了 即使没有test() 这一个也会运行
    def test(*args, **kwargs):
    print("test 开始运行")
    time.sleep(3)
    return '这是test的返回值'

    res = test()
    print(res)
    #输出如下: wrapper开始了。 test 开始运行 wrapper结束: 共用时间:3秒 这是wrapper的返回值

     解包

    a,*d,c=[1,2,3,4,5,6]
    a是1 c是6,中间的全部弄到d中了 ,但是*后面必须跟个变量名
    a,b=b,a 交换a,b的值

    可选择的修饰器

    就在原来修饰器外面添加个选择函数

    import time
    
    def  consumption(func):
        print("消费开始:")
        def inner(*args, **kwargs):
            print("内部消费开始:")
            res = func(*args, **kwargs)
            print("内部消费结束")
            return res
        return  inner
    
    @consumption  
    def chifan():
        time.sleep(3)
        print("我吃完饭了,用来3秒")
    
    @consumption 
    def read_book():
        time.sleep(0.5)
        print("我读完书了,用了0.5")
    
    chifan()
    
    
    #输出如下: 两个消费开始说明,先运行了两次@consumption
    消费开始:
    消费开始:
    内部消费开始:
    我吃完饭了,用来3秒
    内部消费结束


    import time
    def cons(select=1): #在原来外面添加一个选择函数
    def consumption(func):
    print("消费开始:")
    def inner(*args, **kwargs):
    if select == 1:
    print("内部消费1开始:")
    res = func(*args, **kwargs)
    print("内部消费1结束")
    return res
    elif select == 2:
    print("内部消费2开始:")
    res = func(*args, **kwargs)
    print("内部消费2结束")
    return res
    return inner
    return consumption

    @cons(2) #这里可以选择消费类型
    def chifan():
    time.sleep(3)
    print("我吃完饭了,用来3秒")

    @cons(1) #这里可以选择消费类型
    def read_book():
    time.sleep(0.5)
    print("我读完书了,用了0.5")

    chifan()

    read_book()


    #输出如下:

    消费开始:
    消费开始:
    内部消费2开始:
    我吃完饭了,用来3秒
    内部消费2结束
    内部消费1开始:
    我读完书了,用了0.5
    内部消费1结束

     

    多重修饰器

    
    

    def dec1(func):
    print("HHHA:0====>")
    def one():
    print("HHHA:0.1====>")
    func()
    print("HHHA:0.2====>")
    return one


    def dec2(func):
    print("HHHB:0====>")
    def two():
    print("HHHB:0.1====>")
    func()
    print("HHHB:0.2====>")
    return two


    def dec3(func):
    print("HHHC:0====>")
    def three():
    print("HHHC:0.1====>")
    func()
    print("HHHC:0.2====>")
    return three

    @dec1
    @dec2
    @dec3
    def test():
    print("HHHD:0====>test")


    test()

    输出如下:

    HHHC:0====>
    HHHB:0====>
    HHHA:0====>
    HHHA:0.1====>
    HHHB:0.1====>
    HHHC:0.1====>
    HHHD:0====>test
    HHHC:0.2====>
    HHHB:0.2====>
    HHHA:0.2====>

    组装阶段从下到上   test->dec3->dec2->dec1   执行阶段:one->two->three  调用关系从上到下

    函数前阶段,从上到下    

    函数

    函数后阶段:从下到上

    def log(text):
        print("HHHA:0====>")
        def decorator(func):
            print("HHHA:0.1====>")
            def wrapper(*args, **kw):
                print("HHHA:0.1.1====>")
                return func(*args, **kw)
            print("HHHA:0.2====>")
            return wrapper
        print("HHHA:1====>")
        return decorator
    
    @log('execute')
    def now():
        print('HHHB:=====>test')
    
    now()
    
    #输出如下:
    HHHA:0====>
    HHHA:1====>
    HHHA:0.1====>
    HHHA:0.2====>
    HHHA:0.1.1====>
    HHHB:=====>test
    先执行含餐部分
    再执行装饰器部分
    再调用部分

    支付宝     
    您的资助是我最大的动力!
    金额随意,欢迎来赏!
    微信

    如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的关注我

    如果,想给予我更多的鼓励,求打       付款后有任何问题请给我留言!!!

    ------------------------------------------------------------------------------------------
    作者:【周sir】
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    React 16 源码瞎几把解读 【前戏】 为啥组件外面非得包个标签?
    nodejs 使用redis 管理session
    nodejs 优雅的连接 mysql
    mongodb 学习笔记 3 --- 查询
    mongodb 学习笔记 2 --- 修改器
    mongodb 学习笔记--- 基础知识
    看jquery3.3.1学js类型判断的技巧
    FIS3 大白话【一】
    Flutter 插件开发:以微信SDK为例
    最新Android面试题整理,收藏下吧值得拥有!
  • 原文地址:https://www.cnblogs.com/zhouguanglu/p/10178438.html
Copyright © 2011-2022 走看看