四十.python中的闭包

本文介绍了Python闭包,它是一种组织代码的结构,可减少代码复用性。构建外部函数时,内部函数使用外部函数变量,外部函数返回内部函数方法。内部函数无法直接修改外部函数变量值,在Python 2.7中可将闭包变量改成可变类型修改。闭包常用于装饰器和实现面向对象编程。

闭包是什么东西?

闭包是一种组织代码的结构,它同样可以减少代码的复用性。

简单的可以理解为:构建一个(外部)函数时,在该函数内又有一个(内部)函数,内部函数需要使用到外部函数的变量,且外部函数返回的值则是内部函数的方法。

以下通过示例来理解闭包的意思:

#coding:utf-8
def outer(a):#定义一个outer外部函数,a是一个必传参数
    b = 5 #外部函数的变量
    def inner():#内部函数,没有参数
        print a+b #内部函数的语句
    return inner #外部函数返回值时内部函数的方法

if __name__=="__main__": #加入这句后,在其他模块调用时不执行以下执行语句
    c = outer(5)#调用外部函数传入参数5,这个时候外部函数存在两个参数一个a=5,另一个b=10
    #外部函数结束的时候会发现内部函数引用了自己的变量,因此这两个变量不会释放,会绑定给内部函数
    c() #c存了外部函数的返回值,也就是inner内部函数的方法,这里相当于执行inner内部函数
        #内部函数方法为print a+b 则打印结果为10
    d = outer(10)
    d() #结果为15

内部函数的方法是无法直接修改外部函数的变量值。

你可以尝试把以上代码的print a+b 改为 a+=1 然后print a试试,它是会报错的。UnboundLocalError: local variable 'a' referenced before assignment 运行时会报这样的错误,也就是说明a这个外部函数的变量值无法直接修改。

那么在内部函数若要修改在python2.7中需要把闭包(外部函数)变量改成可变类型数据进行修改,比如把变量变成一个列表。

以下为修改外部函数的示例:

#coding:utf-8
def outer(a):#定义一个outer外部函数,a是一个必传参数
    b = 5 #外部函数的变量
    e = [a] #把传入的参数以列表的形式保存在变量名e里面
    def inner():#内部函数,没有参数
        e[0]+=1 #e的下标索引为0的时候就是传入的a值,a+=1则为a=a+1
        print a+b
        print e[0] #打印a+1后的下标索引值
    return inner #外部函数返回值时内部函数的方法

if __name__=="__main__": #加入这句后,在其他模块调用时不执行以下执行语句
    c = outer(5)#调用外部函数传入参数5,这个时候外部函数存在两个参数一个a=5,另一个b=10
    #外部函数结束的时候会发现内部函数引用了自己的变量,因此这两个变量不会释放,会绑定给内部函数
    c() #c存了外部函数的返回值,也就是inner内部函数的方法,这里相当于执行inner内部函数
        #内部函数方法为print a+b 则打印结果为10,print e[0]为5+1 则打印6
    d = outer(10)
    d() #结果为15,11

 

闭包一般是在哪几种情况下使用:

1.装饰器,也就是当我们需要在原来的函数上进行功能添加又不去改变原来函数的结构时可以使用闭包的方法去实现。

2.闭包也是实现面向对象的编程方法之一。

Python 中,闭包(Closure)是一种函数与它所引用的自由变量(即不在函数内部定义的变量)之间的绑定关系。闭包能够“记住”并访问其词法作用域,即使函数在其作用域外执行。闭包的核心特征是函数和其引用环境的结合,使其能够访问并操作外部作用域中的变量 [^2]。 ### 闭包的作用 1. **读取函数内部的变量** 闭包可以访问外部函数中的变量,即使外部函数已经执行完毕。这使得内部函数可以保留并操作外部函数的状态。 2. **保持变量在内存中** 由于闭包对外部作用域中的变量保持引用,这些变量不会被垃圾回收机制回收,从而实现状态的持久化。 3. **封装和数据隐藏** 闭包可用于创建私有变量,避免全局变量的污染,实现类似面向对象编程中的私有属性。 4. **函数工厂** 闭包可以用于创建具有不同行为的函数,基于不同的输入参数生成定制化的函数。 ### 闭包的使用示例 以下是一个简单的闭包示例,演示了如何通过闭包保留外部函数的变量状态: ```python def outer_function(x): def inner_function(): print(f"Value of x: {x}") return inner_function closure_example = outer_function(10) closure_example() # 输出: Value of x: 10 ``` 在上述代码中,`inner_function` 是一个闭包,它捕获了 `outer_function` 中的变量 `x`。即使 `outer_function` 已经执行完毕,`closure_example` 仍然可以访问 `x` 的值 [^1]。 另一个常见的应用场景是使用闭包来实现计数器: ```python def counter(): count = 0 def increment(): nonlocal count count += 1 return count return increment counter_instance = counter() print(counter_instance()) # 输出: 1 print(counter_instance()) # 输出: 2 ``` 在这个例子中,`increment` 函数是一个闭包,它维护了 `count` 变量的状态,每次调用都会递增该变量。这种方式避免了使用全局变量,同时实现了数据的封装 [^2]。 ### 注意事项 - **内存消耗**:由于闭包会保持对外部变量的引用,可能会导致内存占用增加,特别是在大量使用闭包时需要注意内存管理 [^3]。 - **不可变变量**:在 Python 中,如果闭包引用的是外部函数的局部变量,并且尝试修改其值,则必须使用 `nonlocal` 关键字声明该变量,否则会创建一个新的局部变量 。 - **循环变量问题**:在闭包中引用循环变量时,需要注意变量作用域问题,可能会导致所有闭包共享同一个变量值,而不是各自独立的值。 ### 相关概念 闭包Python 中可以通过 `__closure__` 属性来查看其捕获的变量信息。例如: ```python def outer(x): def inner(): return x return inner closure = outer(5) print(closure.__closure__) # 查看闭包捕获的变量 ``` 通过 `__closure__` 属性,可以检查闭包是否正确捕获了外部变量及其内存地址 [^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值