zoukankan      html  css  js  c++  java
  • Python 闭包的相关知识

    Python 闭包相关知识

    闭包字面意思,是封闭的东西,为了保证数据的安全。

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

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

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

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

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

    ​ …………

    实现以上需求,方案一:不能保证数据安全
    l1 = []		# 全局变量,数据不安全,容易被误操作改变。
    li = []		# 相似的变量
    def make_averager(new_value):
        l1.append(new_value)
        total = sum(l1)
        return total / len(l1)    
    print(make_averager(100000))	# 100000.0
    print(make_averager(110000))	# 105000.0
    l1.append(34556)	# 本来要对li进行操作,但是不小心追加错了,造成最终结果出错。
    print(make_averager(120000))	# 83364.0
    
    方案二:使用闭包,外部无法对数据修改,只能以特定的渠道进行调用。
    def make_averager():
        l1 = []                         # 将l1放置在函数内,变成了局部变量,
        def averager(new_value):        # l1在这里被嵌套函数averager调用了,
            l1.append(new_value)        # 列表l1和函数averager之间产生了一个绑定关系,
            return sum(l1) / len(l1)
        print(locals())
        return averager
    avg = make_averager()               # 接下来嵌套函数averager被赋值给了avg变量,
    print(avg(100000))                  # 所以l1虽然在全局变量列表中已经消失,不可调用,但却真实存在,
    # l1.append(54464)                  # 这行代码调用将出错
    print(avg(110000))                  # 只有通过avg变量调用才能对l1进行改变,
    print(avg(90000))                   # 这个现象就是闭包。
    print(globals())
    
    1. 闭包的定义:

      • 闭包是嵌套在函数中的函数。
      • 内层函数对外层函数的变量(非全局变量)的引用(使用),就会形成闭包。
    2. 闭包的现象:

      • 被引用的非全局变量也称作自由变量,这个自由变量会与内层函数产生一个绑定关系,自由变量不会在内存中消失
    3. 闭包的作用:保存局部信息不被销毁,保证数据的安全性。

    4. 闭包的应用:

      • 可以保存一些非全局变量但是不易被销毁、改变的数据。
      • 装饰器。
    5. 判断是否有闭包:

      • 使用代码判断是否存在闭包现象,只需要判断是否存在有“自由变量”即可,判断代码为:

        def func(a, b):		# 这段代码虽然看上去变量a,b为全局变量,
            def inner():	# 但是传入函数内将生成一个局部变量a,b
                print(a)	# 函数内部的a,b变量和外面的并不是同一个
                print(b)	
            return inner
        a = 2
        b = 3
        ret = func(a, b)	# 所以这条命令之后将形成一个闭包现象 
        print(ret.__code__.co_freevars)	# 以这条指令判断是否存在“自由变量”
        >>>('a', 'b')		# 运行结果有a,b两个变量属于自由变量,可以断定上面代码存在闭包现象。
        
    6. 查看函数相关的其他参数:

      • 有一些函数的属性是可以获取到此函数是否拥有自由变量的,如果此函数拥有自由变量,那么就可以侧面证明其是否是闭包函数了,以下还有一些参数,仅供了解:

        def make_averager():
            series = []
            def averager(new_value):
                series.append(new_value)
                total = sum(series)
                return total/len(series)
            return averager
        avg = make_averager()
        
        # 函数名.__code__.co_freevars 查看函数的自由变量
        print(avg.__code__.co_freevars)  # ('series',)
        # 函数名.__code__.co_varnames 查看函数的局部变量
        print(avg.__code__.co_varnames)  # ('new_value', 'total')
        # 函数名.__closure__ 获取具体的自由变量对象,也就是cell对象。
        # (<cell at 0x0000020070CB7618: int object at 0x000000005CA08090>,)
        # cell_contents 自由变量具体的值
        print(avg.__closure__[0].cell_contents)  # []
        
  • 相关阅读:
    android 打包错误
    mysql innoDB 挂了的临时解决方案
    android notification 传值关键
    maven eclipse 插件下载地址
    微信html5开发选哪一个
    android AsyncTask 只能在线程池里单个运行的问题
    关于Fragment 不响应onActivityResult的情况分析 (
    Android-BaseLine基础性开发框架
    linux网络流量实时监控工具之iptraf
    android 圆角按钮和按钮颜色
  • 原文地址:https://www.cnblogs.com/amwkvi/p/13747874.html
Copyright © 2011-2022 走看看