python基础-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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值