Python 闭包

1. 引例

        这里有一个atm()函数,实现了存款和取款的功能,思考一下这样写有什么缺点:        

account_amount = 0  # 用户余额

def atm(num, deposit=True):
    global account_amount
    if deposit:
        account_amount += num
        print(f"存款+{num},当前余额为:{account_amount}")
    else:
        if account_amount >= num:
            account_amount -= num
            print(f"取款-{num},当前余额为:{account_amount}")
        else:
            print("余额不足")

atm(100)
atm(100)
atm(200,False)

        运行结果:

2. 闭包的概念

        在引例中使用了一个全局变量account_amount来记录用户余额的值。在atm()函数中访问并修改了account_amount的值,从而实现余额的增减。这样处理会导致account_amount允许被其他对象所更改,甚至被其他文件import时也可以修改account_amount的值。这不是我们所期望的。于是引出了闭包的概念。

闭包是指在一个函数内部定义的函数,这个内部函数可以引用其外部函数中的变量,即使外部函数已经执行完毕并退出了。这种内部函数连同它引用的外部函数中的变量一起被称为闭包(closure)。

闭包的关键特性在于它能够记住并访问定义时的作用域中的变量,即使在闭包被调用时,那个作用域已经不存在了。

闭包的特性:

  1. 函数嵌套:闭包是在一个函数内部定义另一个函数。
  2. 自由变量:内部函数引用了外部函数的变量。
  3. 返回值是内部函数:外部函数返回内部函数,这个内部函数即为闭包。

         以下是一个简单的闭包示例:

def outer(text):
    def inner():
        print(text)
    return inner

# 创建闭包
closure = outer("Hello, World!")

# 调用闭包
closure()  # 输出: Hello, World!

         在这个示例中,text的作用域是整个外部函数outer()而不是全局,但是内部函数inner()也可以访问text的值。这样就避免了引例中全局变量被修改的风险。

        (简单来说,示例中的account_amount和这里的text在功能上相同,但是作用域不同。使用闭包的方式,减小了变量的作用域,更加的安全)

3.  闭包的实际应用

        闭包可以用来创建工厂函数、装饰器、回调函数等。下面是一个利用闭包创建简单计数器的例子:

def make_counter():
    count = 0

    def counter():
        nonlocal count  # 声明 count 是外部函数的变量
        count += 1
        return count

    return counter

# 创建两个独立的计数器
counter1 = make_counter()
counter2 = make_counter()

print(counter1())  # 输出: 1
print(counter1())  # 输出: 2
print(counter2())  # 输出: 1
print(counter2())  # 输出: 2
print(counter1())  # 输出: 3

        每个计数器函数都有自己独立的 count 变量,这就是闭包的强大之处。       

        可以注意到,这个例子中有一个nonlocal的关键字,简单来说就是允许内部函数(counter())修改外层的变量。确切地说nonlocal关键字是 Python 中用于在嵌套函数中引用外层(但不是全局作用域)变量的一种方式。它的作用是声明一个变量在外层函数中的作用域,并允许在内层函数中对其进行修改。nonlocal 关键字避免了局部变量的遮蔽问题,使得内层函数可以访问并修改外层函数的变量。

4. 使用闭包的atm()

        我想,关于闭包是什么和如何使用,已经讨论清楚了,那么我们使用闭包的思想重写atm()函数。如下:

def account_create(account_amount=0):
    def atm(num, deposit=True):
        nonlocal account_amount
        if deposit:
            account_amount += num
            print(f"存款+{num},当前余额为:{account_amount}")
        else:
            if account_amount >= num:
                account_amount -= num
                print(f"取款-{num},当前余额为:{account_amount}")
            else:
                print("余额不不足")
    return atm

atm = account_create()
atm(200)
atm(300)
atm(400, False)

        运行结果:

  • 18
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值