• 深入浅出讲解python闭包


    一、定义

    在 Python 中,当一个函数内部定义的函数引用了外部函数的局部变量时,就形成了一个闭包。这个内部函数可以访问并修改外部函数的局部变量,而这些局部变量的状态会一直被保存在闭包中,即使外部函数已经执行完毕。

    这种机制使得闭包可以实现一些特殊的功能,例如记忆化(Memoization)和实现私有变量等。闭包可以在函数内部保存一些状态,并且这些状态对外部是不可见的,从而实现了一定程度上的信息隐藏和封装。

    1. def outer_function():
    2. x = 10
    3. def inner_function():
    4. nonlocal x # 声明使用外部函数的局部变量 x
    5. x += 5
    6. return x
    7. return inner_function
    8. closure = outer_function()
    9. print(closure()) # 输出结果为 15
    10. print(closure()) # 输出结果为 20

    在这个示例中,inner_function 就是一个闭包,它引用了外部函数 outer_function 中的局部变量 x。每次调用 closure() 都会修改并返回 x 的值,而这个状态是被保存在闭包中的。


    二、通过一个例子全面剖析一下闭包这个概念。

    需求:实现银行系统的余额变化。

    方式一:全局变量+函数

    1. balance = 1000
    2. def deposit(amount):
    3. global balance
    4. balance += amount
    5. print(f"成功存入 {amount} 元,当前余额为 {balance} 元")
    6. def withdraw(amount):
    7. global balance
    8. if amount <= balance:
    9. balance -= amount
    10. print(f"成功取出 {amount} 元,当前余额为 {balance} 元")
    11. else:
    12. print("余额不足,取款失败")
    13. def check_balance():
    14. print(f"当前余额为 {balance} 元")
    15. # 存款和取款操作
    16. deposit(500) # 存入 500 元
    17. withdraw(200) # 取出 200 元
    18. balance=10
    19. deposit(500) # 存入 500 元
    20. check_balance() # 查看余额

    结果

    成功存入 500 元,当前余额为 1500 元

    成功取出 200 元,当前余额为 1300 元

    成功存入 500 元,当前余额为 510 元

    当前余额为 510 元

    缺点:全局变量不安全,可以被随意访问和修改。

    使用全局变量的方式虽然可以实现功能,但存在一些潜在问题:

    1. 可变性:全局变量的值是可变的,任何函数都可以直接修改它,这增加了程序出错的可能性,尤其在大型程序中更容易出现问题。

    2. 可见性:全局变量对整个程序都是可见的,这意味着任何部分都可以修改它,从而导致程序行为难以预测。

    3. 扩展性:如果需要管理多个账户,全局变量的方式就显得力不从心,因为很难将多个账户的信息独立地封装起来。


    方案二:类

    1. class BankAccount:
    2. def __init__(self, initial_balance):
    3. self.balance = initial_balance
    4. def deposit(self, amount):
    5. self.balance += amount
    6. print(f"成功存入 {amount} 元,当前余额为 {self.balance} 元")
    7. def withdraw(self, amount):
    8. if amount <= self.balance:
    9. self.balance -= amount
    10. print(f"成功取出 {amount} 元,当前余额为 {self.balance} 元")
    11. else:
    12. print("余额不足,取款失败")
    13. def check_balance(self):
    14. print(f"当前余额为 {self.balance} 元")
    15. # 创建账户
    16. account = BankAccount(1000)
    17. account.balance=550
    18. # 存款和取款操作
    19. account.deposit(500) # 存入 500 元
    20. account.withdraw(200) # 取出 200 元
    21. account.check_balance() # 查看余额

    结果

    成功存入 500 元,当前余额为 1050 元

    成功取出 200 元,当前余额为 850 元

    当前余额为 850 元

    缺点:共有属性也能被对象访问修改,不安全。


    方案三:类+私有属性

    1. class BankAccount:
    2. def __init__(self, initial_balance):
    3. self.__balance = initial_balance
    4. def deposit(self, amount):
    5. self.__balance += amount
    6. print(f"成功存入 {amount} 元,当前余额为 {self.__balance} 元")
    7. def withdraw(self, amount):
    8. if amount <= self.__balance:
    9. self.__balance -= amount
    10. print(f"成功取出 {amount} 元,当前余额为 {self.__balance} 元")
    11. else:
    12. print("余额不足,取款失败")
    13. def check_balance(self):
    14. print(f"当前余额为 {self.__balance} 元")
    15. account = BankAccount(1000)
    16. account.deposit(500)
    17. account.withdraw(200)
    18. account.check_balance()

    结果:

    成功存入 500 元,当前余额为 1500 元

    成功取出 200 元,当前余额为 1300 元

    当前余额为 1300 元

    问题得到解决。


    方案四:闭包

    1. def create_account(initial_balance):
    2. balance = initial_balance
    3. def deposit(amount):
    4. nonlocal balance
    5. balance += amount
    6. print(f"成功存入 {amount} 元,当前余额为 {balance} 元")
    7. def withdraw(amount):
    8. nonlocal balance
    9. if amount <= balance:
    10. balance -= amount
    11. print(f"成功取出 {amount} 元,当前余额为 {balance} 元")
    12. else:
    13. print("余额不足,取款失败")
    14. def check_balance():
    15. print(f"当前余额为 {balance} 元")
    16. return deposit, withdraw, check_balance
    17. # 创建账户
    18. deposit, withdraw, check_balance = create_account(1000)
    19. # 存款和取款操作
    20. deposit(500) # 存入 500 元
    21. print(deposit)
    22. withdraw(200) # 取出 200 元
    23. check_balance() # 查看余额
    24. # 创建账户
    25. deposit1, withdraw1, check_balance1 = create_account(10000)
    26. # 存款和取款操作
    27. deposit1(500) # 存入 500 元
    28. print(deposit1)
    29. withdraw1(200) # 取出 200 元
    30. check_balance1() # 查看余额

    结果

    成功存入 500 元,当前余额为 1500 元

    .deposit at 0x0000020DCC711990>

    成功取出 200 元,当前余额为 1300 元

    当前余额为 1300 元

    成功存入 500 元,当前余额为 10500 元

    .deposit at 0x0000020DCC711A20>

    成功取出 200 元,当前余额为 10300 元

    当前余额为 10300 元

    完美解决了问题


    三、辨析

    闭包和类是两种不同的概念,它们在编程中有着不同的用途和特点。

    闭包(Closure)是指可以在其词法作用域之外执行的函数,但仍然保持对其作用域内变量的引用。换句话说,闭包是函数及其相关的引用环境的组合。闭包可以用来封装状态、实现私有变量等功能。在 Python 中,当一个函数内部定义的函数引用了外部函数的局部变量时,就形成了一个闭包。

    类(Class)则是面向对象编程中的重要概念,它用来描述具有相似属性和行为的对象的模板。类由属性(成员变量)和方法(成员函数)组成,可以通过实例化来创建对象,并且支持继承、多态等面向对象的特性。类的主要作用是封装数据和操作数据的方法,以及实现代码复用和抽象。

    下面是闭包和类的一些区别:

    1. 封装方式不同:闭包是一种函数式编程的封装方式,通过函数和其引用环境来封装状态和行为;类是一种面向对象编程的封装方式,通过属性和方法来封装数据和操作。

    2. 状态的保存方式不同:闭包通过引用环境来保存状态,而类通过实例变量和类变量来保存状态。

    3. 范围不同:闭包通常用于封装一些局部状态,提供函数式编程的功能;类则通常用于描述对象的行为和属性,提供面向对象编程的特性。

    总的来说,闭包和类都是用于封装和抽象的工具,但其应用场景和实现方式有所不同。在实际编程中,可以根据具体的需求和问题选择合适的工具来实现相应的功能。

  • 相关阅读:
    【云原生】DevOps(七):Kubernetes编排工具
    java 桥接方法
    STM32+FreeRTos+Cube MX实现LED闪烁
    Apache HttpClient 5 使用详细教程
    vncserver远程管理kvm虚拟机
    springboot+微信小程序基于微信小程序的化妆品商城系统设计与实现毕业设计源码041152
    Springboot快递管理系统1k61h计算机毕业设计-课程设计-期末作业-毕设程序代做
    计算机网络之传输层 + 应用层
    ssm基于微信小程序的高校课堂教学管理系统--(ssm+uinapp+Mysql)
    最短路径算法模版(Dijkstra, Bellman Ford, SPFA, floyd)及例题「C++实现」
  • 原文地址:https://blog.csdn.net/douyu0814/article/details/134501003