• 18闭包


    闭包:

    只能存在嵌套的函数中

    • 封闭的东西:保证数据安全
    • 内层函数对外层函数非全局变量的引用(使用),就会形成闭包
    • 被引用的全局变量被称作自由变量,这个自由变量会与内层函数产生一个绑定关系
    • 自由变量不会再内存中消失
    def outer():
        def inner(): #被执行的时机是不确定的
            print ("你好")
        return inner  # 把函数作为返回值返回
    
    ret = outer()
    ret()  #你好
    
    def outer():
        a = 20
        def inner(): #被执行的时机是不确定的
            print (a) #内层函数对外层函数的局部变量的使用叫做闭包
            print ("你好")
        return inner  # 把函数作为返回值返回
    
    ret = outer()
    ret()  
    # 20 
    # 你好
    
    def func():
        a = 20  #局部变量,在外面不能修改
        print (a)
    
    func()  #20
    
    a = 30
    print (a) # 30
    
    

    由于闭包这个概念比较难以理解,尤其是初学者来说,相对难以掌握,所以我们通过示例去理解学习闭包。

    给大家提个需求,然后用函数去实现:完成一个计算不断增加的系列值的平均值的需求。

    例如:整个历史中的某个商品的平均收盘价。什么叫平局收盘价呢?就是从这个商品一出现开始,每天记录当天价格,然后计算他的平均值:平均值要考虑直至目前为止所有的价格。

    比如大众推出了一款新车:小白轿车。

    第一天价格为:100000元,平均收盘价:100000元

    第二天价格为:110000元,平均收盘价:(100000 + 110000)/2 元

    第三天价格为:120000元,平均收盘价:(100000 + 110000 + 120000)/3 元


    方案一

    l1 = [] # 全局变量
    def make_averager(new_value):
        l1.append(new_value)
        total = sum(l1)
        return total / len(l1)
    
    print(make_averager(100000))
    print(make_averager(110000))
    print(make_averager(120000))
    # 100000.0
    # 105000.0
    # 110000.0
    
    
    • 从方案一中可以看出,基本上完成了我们的要求,但是这个代码相对来说是不安全的,因为你的这个 l1 列表是一个全局变量,只要是全局作用域的任何地方,都可能对这个列表进行改变。
      如:
    li = []
    
    
    def make_averager(new_value):
        li.append(new_value)
        total = sum(li)
        return total / len(li)
    
    
    print(make_averager(100000))
    print(make_averager(110000))
    li.append(666)  # 如果对数据进行相应改变,那么你的平均收盘价就会出现很大的问题。
    print(make_averager(120000))
    
    # 100000.0
    # 105000.0
    # 82666.5
    
    

    那么怎么办呢?有人说,你把他放在函数中不就行了,这样不就是局部变量了么?数据不就相对安全了么?这样计算的结果是不正确的,那是因为执行函数,会开启一个临时的名称空间,随着函数的结束而消失,所以你每次执行函数的时候,都是重新创建这个列表。

    def make_averager(new_value):
        l1 = []
        l1.append(new_value)
        total = sum(l1)
        return total / len(l1)
    
    print(make_averager(100000))  # 100000.0
    print(make_averager(110000))  # 110000.0
    print(make_averager(120000))  # 120000.0
    

    那么这怎么做呢?这种情况下,就需要用到闭包了,我们用闭包的思想改一下这个代码

    def make_averager():
        l1 = []
        def averager(new_value):
            l1.append(new_value)
            total = sum(l1)
            return total / len(l1)
        return averager
    
    abc = make_averager() # 等于averager
    print(abc(100000))
    print(abc(110000))
    print(abc(120000))
    
    # 100000.0
    # 105000.0
    # 110000.0
    
    
  • 相关阅读:
    Findbugs初探-使用idea获取findbugs插件
    idea 14运行java工程报错-Dmaven.multiModuleProjectDirectory system propery is not set. Check $M2_HOME environment variable and mvn script match.
    Linux定时任务
    模块和包
    流程控制&&函数
    Python 变量与数据类型
    使用代码上传文件示例
    好用的代码示例
    JedisCluster API 整理
    springboot实现转发和重定向
  • 原文地址:https://www.cnblogs.com/gemoumou/p/13635317.html
Copyright © 2020-2023  润新知