likes
comments
collection
share

Python闭包入门

作者站长头像
站长
· 阅读数 57

关于闭包

闭包实际上是一个嵌套函数,且外部函数的返回值是一个函数,内部函数需要使用到外部函数定义的变量,一个简单的闭包函数如下:

def band():
  """
    存钱罐
  """
  money = 0  # 初始余额为0
  def add(a:float):
    nonlocal money
    money += a
    return money
  return add
if __name__ == '__main__':
  add = band()  # 获取add函数
  m = add(10)  # 存入10元
  print(f"当前余额为:{m}")
  m = add(-5.21)
  print(f"当前余额为:{m}")

这里通过一个简单的存钱罐实例来创建了一个闭包函数,其中闭包函数相较于普通函数而言,优势在于,可以持久化保存变量

关于持久化保存变量

首先要明白作用域这个概念,作用域分为全局作用域局部作用域两种,全局作用域指的是全局变量的作用域,一般在外部创建,在程序的整个生命周期内都可以使用,且可以在任意地方使用;局部作用域是指局部变量的作用域,在内部创建,运行时创建,结束时销毁。

MAX_NUM = 10  # 这里的MAX_NUM就是全局变量,全局可用
def count(a:int):
    num = 0  # 这里的num就是局部变量,只能在count函数内部使用,且每次运行count函数时创建,count函数结束时销毁
    if a > MAX_NUM:
        num = a  # 修改局部变量,仅在当前有效,第二次运行函数时,变量的值仍然是0
        c = a - MAX_NUM
    c = a + num
    print(f"当前num值为:{num}")
    return c
c = count(100)
print(c)
d = count(5)
print(d)

上面函数的打印结果如下

当前num值为:100 
200 
当前num值为:0 
5

从这里我们就可以看出来,函数创建的局部变量,仅在函数当前运行时有效,函数返回后,局部变量将会被销毁,如果我们有类似存钱罐这样的需求,也就是持久的保存一个变量,将这个变量写在函数中明显是不行的。 那么使用全局变量呢?

使用全局变量实现持久化变量

Money = 0
def add(a:float):
    global Money
    Money += a
    return Money

add(50)
print(f"当前余额为:{Money}")
add(-30)
print(f"当前余额为:{Money}")
Money = 15
add(10)
print(f"当前余额为:{Money}")

上面的代码打印结果如下

当前余额为:50 当前余额为:20 当前余额为:25

你会发现前面两次的结果是在我们预期中的,但是第三次明显就不是预期中的内容了,这是因为全局变量的全局可用导致的异常,因为全局可用,所以我们可以在任意地方修改这个变量,这也就容易引发结果的混乱。而闭包函数中的外部变量也是一个局部变量,仅在闭包函数内部可用,外部是无法修改它的,这样就保证了变量的安全性。那么当闭包函数中的变量和全局变量的变量名一致时,是否会引发异常呢?

当闭包函数中的变量和全局变量一致时

num = 100
def ADD():
    num = 10

    def add(a:float):
        return a + num
    return add

A = ADD()
c = A(5)
print(c)
d = A(10)
print(d)

上面代码的执行结果为

15 20

可以看到,当闭包函数中的变量名称和全局变量的名称一致时,内部函数使用的是离它自己最近的变量,而不是全局变量。 这也就涉及到了函数的变量的取值过程,如果我们使用一个变量时,变量没有被定义,那么Python将自动从内到外的去寻找这个变量,也就是全局变量是最后的取值,如果查询到全局变量,且全局变量中也没有这个变量的话,Python将直接产生异常。

闭包总结

通过上面的内容,可以发现闭包的好处主要有两个方面

变量可以持久化保存,并不会随着函数的返回而销毁,因为外部函数的返回值是内部函数,所以只要外部函数没有被del掉,变量就可以实现持久化存储(外部函数的变量) 想较于全局变量的持久化存储,闭包函数中的变量更有安全性,因为不能被随意更改

转载自:https://juejin.cn/post/7375030479496331274
评论
请登录