python闭包的定义及注意事项

简介:python闭包函数的定义,闭包函数使用全局变量,闭包函数的应用

闭包函数的定义

闭包是函数+环境变量组成,其中环境变量是指闭包中的变量,闭包函数的子函数中的变量不能与闭包中的函数名称相同。例如下方案例中,变量a时闭包函数的环境变量,这个环境变量不能在子函数curve中更新,否则整个闭包函数就会变成普通的函数,闭包相关的操作也将失效:

# 定义闭包函数
def curve_pre():
    a = 25
    # 定义闭包的回调函数
    def curve(x):
        return a * x * x
    return curve

f = curve_pre()
res = f(11)

print(res)

闭包中的环境变量全部存储在一个内置的变量【__closure__】中,如果我们想要查看某个闭包的所有变量可以使用如下方式:

def curve_pre():
    a = 25
    def curve(x):
        return a * x * x
    return curve

f = curve_pre()

print( f.__closure__ ) #打印结果:

注意了,如果我们在子函数curve中更新闭包函数的环境变量,那么此时,__closure__ 返回空,因为闭包函数认为变量a不是环境变量,会把变量a变成局部变量,这也破坏了闭包的定义。

实际应用

假设我们需要封装函数来计算一个人的步行的距离,一般情况下都会使用如下方式:

origin = 0

def go(step):
    global origin
    origin  = origin + step
    return origin

# 每走n步记录一次
print(go(2)) # 打印结果:
print(go(2)) # 打印结果:
print(go(2)) # 打印结果:

注意:go函数中的 global 的作用是申明某个变量为全局变量

虽然我们可以通过全局变量方式去保存历史数据,但是这种方式可能会破坏代码的架构性,很容易搞混变量,毕竟全局变量很容被其他地方更新。但是闭包就可以很好的解决,具体代码如下:

def factory():
    origin = 0
    def go(step):
        origin = origin + step
        return origin
    return go

f = factory()

print(f(2))
print(f(2))
print(f(2))

这样一来就不会涉及到全局变量污染的问题了。

这里的初始值是固定的,为了代码的可维护性,有的时候需要从外传值来定义初始值,闭包也是支持的,在子函数中使用时只需要通过关键字 nonlocal 申明即可,具体代码如下:

def factory(origin):
    def go(step):
        nonlocal origin
        origin = origin + step
        return origin
    return go

origin = 10
f = factory(origin)

print(f(2))
print(f(2))
print(f(2))

虽然闭包可以解决全局变量污染的问题,但是闭包的方式非常容易导致内存泄漏,因为闭包函数的环境变量单独存储在__closure__ 中,这里面的变量无法及时的得到内存的释放。在日常工作做我们需要自己去衡量是否使用闭包,在什么场景下使用等问题

有遗漏或者不对的可以在我的公众号留言哦

编程经验共享公众号二维码

编程经验共享公众号二维码
更多内容关注公众号
Copyright © 2021 编程经验共享 赣ICP备2021010401号-1