VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > python入门教程 >
  • python--高级语法 8

5、闭包

5.1闭包的定义:

  1. 闭包是嵌套在函数中的函数。

  2. 闭包必须是内层函数对外层函数的变量(非全局变量)的引用。

闭包的现象:

  • 被引用的非全局变量也称作自由变量,这个自由变量会与内层函数产生一个绑定关系。

  • 自由变量不会再内存中消失。

  1. '''
    由于闭包这个概念比较难以理解,尤其是初学者来说,相对难以掌握,所以我们通过示例去理解学习闭包。
    给大家提个需求,然后用函数去实现:完成一个计算不断增加的系列值的平均值的需求。
    
    例如:整个历史中的某个商品的平均收盘价。什么叫平局收盘价呢?就是从这个商品一出现开始,每天记录当天价格,然后计算他的平均值:平均值要考虑直至目前为止所有的价格。
    比如大众推出了一款新车:小白轿车。
    第一天价格为:100000元,平均收盘价:100000元
    第二天价格为:110000元,平均收盘价:(100000 + 110000)/2 元
    第三天价格为:120000元,平均收盘价:(100000 + 110000 + 120000)/3 元
    ........
    '''
    # 封闭的东西: 保证数据的安全。
    
    # 方案一:
    # l1=[]  #全局变量
    # def make_averager(new_value):
    #     l1.append(new_value)
    #     total=sum(l1)
    #     average=total/len(l1)
    #     return average
    #
    # print(make_averager(100000))
    # print(make_averager(110000))
    # print(make_averager(120000))
    
    # 方案二: 数据安全,l1不能是全局变量。
    # def make_averager(new_value):
    #     l1 = []
    #     l1.append(new_value)
    #     total = sum(l1)
    #     averager = total/len(l1)
    #     return averager
    
    # print(make_averager(100000))
    # print(make_averager(110000))
    # 此方案不行 因为每次执行的时候,l1列表都会重新赋值成空列表[]
    
    # 方案三: 闭包
    
    def make_averager():
        l1 = []
        def averager(new_value):
            l1.append(new_value)
            total = sum(l1)
            averager1 = total/len(l1)
            return averager1
        return averager
    
    avg=make_averager()      #avg这个变量得到是 averager这个函数名
    print(avg(100000))              #相当于执行---averager(100000)
    print(avg(110000))
    
    #思考:avg=make_averager() 这句代码执行完,理论上l1这个列表消失了,可是为什么没有消失?
    #因为产生了闭包
    
    100000.0
    105000.0
    
    Process finished with exit code 0
    

5.2闭包的作用:

  • 保存局部信息不被销毁,保证数据的安全性

5.3如何判断一个嵌套函数是不是闭包

  • 1,闭包只能存在嵌套函数中
  • 2, 内层函数对外层函数非全局变量的引用(使用),就会形成闭包。
# 例一:
def wrapper():
    a = 1
    def inner():
        print(a)
    return inner
ret = wrapper()
#例一是闭包

# 例二:
a = 2
def wrapper():
    def inner():
        print(a)
    return inner
ret = wrapper()
#例二不是闭包
# 例三:

def wrapper(a,b):
    def inner():
        print(a)
        print(b)
    return inner
a = 2
b = 3
ret = wrapper(a,b)
#也是闭包

5.4如何用代码判断闭包?

  • 查看这个函数有没有自由变量就行了
# 函数名.__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)  # []

上面例三最难判断是不是闭包,为了进一步确认,用代码判断闭包

# 例三:

def wrapper(a,b):
    def inner():
        print(a)
        print(b)
    return inner
a = 2
b = 3
ret = wrapper(a,b)

#如何用代码判断闭包?
print(ret.__code__.co_freevars)

('a', 'b')

Process finished with exit code 0

5.5闭包的应用

  1. 可以保存一些非全局变量但是不易被销毁、改变的数据。
  2. 装饰器。

5.6闭包面试题怎么问?

  • 什么是闭包? 闭包有什么作用。

出处:https://www.cnblogs.com/wushaofan/p/17156647.html
 

相关教程