深入浅出讲解python闭包

深入浅出讲解python闭包_第1张图片

一、定义

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

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

def outer_function():
    x = 10
    def inner_function():
        nonlocal x  # 声明使用外部函数的局部变量 x
        x += 5
        return x
    return inner_function
​
closure = outer_function()
print(closure())  # 输出结果为 15
print(closure())  # 输出结果为 20

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

深入浅出讲解python闭包_第2张图片


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

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

方式一:全局变量+函数

balance = 1000
def deposit(amount):
    global balance
    balance += amount
    print(f"成功存入 {amount} 元,当前余额为 {balance} 元")
​
def withdraw(amount):
    global balance
    if amount <= balance:
        balance -= amount
        print(f"成功取出 {amount} 元,当前余额为 {balance} 元")
    else:
        print("余额不足,取款失败")
​
def check_balance():
    print(f"当前余额为 {balance} 元")
​
# 存款和取款操作
deposit(500)  # 存入 500 元
withdraw(200)  # 取出 200 元
balance=10
deposit(500)  # 存入 500 元
check_balance()  # 查看余额

结果

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

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

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

当前余额为 510 元

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

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

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

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

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


方案二:类

class BankAccount:
    def __init__(self, initial_balance):
        self.balance = initial_balance
​
    def deposit(self, amount):
        self.balance += amount
        print(f"成功存入 {amount} 元,当前余额为 {self.balance} 元")
​
    def withdraw(self, amount):
        if amount <= self.balance:
            self.balance -= amount
            print(f"成功取出 {amount} 元,当前余额为 {self.balance} 元")
        else:
            print("余额不足,取款失败")
​
    def check_balance(self):
        print(f"当前余额为 {self.balance} 元")
​
# 创建账户
account = BankAccount(1000)
account.balance=550
# 存款和取款操作
account.deposit(500)  # 存入 500 元
account.withdraw(200)  # 取出 200 元
account.check_balance()  # 查看余额

结果

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

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

当前余额为 850 元

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


方案三:类+私有属性

class BankAccount:
    def __init__(self, initial_balance):
        self.__balance = initial_balance
​
    def deposit(self, amount):
        self.__balance += amount
        print(f"成功存入 {amount} 元,当前余额为 {self.__balance} 元")
​
    def withdraw(self, amount):
        if amount <= self.__balance:
            self.__balance -= amount
            print(f"成功取出 {amount} 元,当前余额为 {self.__balance} 元")
        else:
            print("余额不足,取款失败")
​
    def check_balance(self):
        print(f"当前余额为 {self.__balance} 元")
​
account = BankAccount(1000)
account.deposit(500)
​
account.withdraw(200)
account.check_balance()

结果:

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

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

当前余额为 1300 元

问题得到解决。


方案四:闭包

def create_account(initial_balance):
    balance = initial_balance
    def deposit(amount):
        nonlocal balance
        balance += amount
        print(f"成功存入 {amount} 元,当前余额为 {balance} 元")
​
    def withdraw(amount):
        nonlocal balance
        if amount <= balance:
            balance -= amount
            print(f"成功取出 {amount} 元,当前余额为 {balance} 元")
        else:
            print("余额不足,取款失败")
​
    def check_balance():
        print(f"当前余额为 {balance} 元")
​
    return deposit, withdraw, check_balance
​
# 创建账户
deposit, withdraw, check_balance = create_account(1000)
​
# 存款和取款操作
deposit(500)  # 存入 500 元
print(deposit)
withdraw(200)  # 取出 200 元
check_balance()  # 查看余额
​
# 创建账户
deposit1, withdraw1, check_balance1 = create_account(10000)
# 存款和取款操作
deposit1(500)  # 存入 500 元
print(deposit1)
withdraw1(200)  # 取出 200 元
check_balance1()  # 查看余额

结果

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

.deposit at 0x0000020DCC711990>

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

当前余额为 1300 元

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

.deposit at 0x0000020DCC711A20>

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

当前余额为 10300 元

完美解决了问题


三、辨析

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

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

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

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

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

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

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

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

深入浅出讲解python闭包_第3张图片

深入浅出讲解python闭包_第4张图片

你可能感兴趣的:(软件工程,python编程实践,人工智能,python,开发语言)