🧠 什么是闭包?
闭包是一个函数对象,它不仅记住它的代码逻辑,还记住了定义它时的自由变量(即非全局也非局部,但被内部函数引用的变量)。即使外部函数已经执行完毕,这些自由变量的值仍然保存在内存中,可以通过闭包访问和使用。
简单来说:
-
当一个嵌套的函数引用了其外部函数中的变量,并且这个嵌套函数可以在其外部函数之外被调用时,就形成了一个闭包。
✅ 闭包的基本结构
def outer_function(x):def inner_function(y):return x + yreturn inner_function
closure = outer_function(10)
print(closure(5)) # 输出: 15
在这个例子中,inner_function
是 outer_function
的内部函数,并且引用了 outer_function
的参数 x
。当 outer_function
返回 inner_function
时,尽管 outer_function
已经执行结束,但是 inner_function
依然保留了对外部变量 x
的引用,这就形成了一个闭包。
✅ 闭包的工作原理
闭包允许你在一个函数内创建并返回另一个函数,而后者能够“记住”前者内部的变量状态。这种特性对于需要保持某些状态的应用场景特别有用,比如计数器等。
示例:简单的计数器
def make_counter():count = 0def counter():nonlocal count # 使用 nonlocal 声明 count 是外部函数中的变量count += 1return countreturn counter
counter = make_counter()
print(counter()) # 输出: 1
print(counter()) # 输出: 2
print(counter()) # 输出: 3
在这个例子中,make_counter
函数返回了一个闭包 counter
,它可以不断增加并返回一个计数值。注意这里使用了 nonlocal
关键字来表明我们要修改的是外部函数中的 count
变量。
✅ 为什么使用闭包?
-
封装:闭包可以帮助我们封装一些数据,避免全局变量的污染。
-
状态保持:通过闭包,我们可以轻松地实现带有状态的函数。
-
减少命名冲突:由于闭包内部使用的变量对外部不可见,因此减少了命名冲突的风险。
✅ 闭包与装饰器
闭包的一个常见应用场景就是作为装饰器的基础。装饰器本质上也是一个闭包,它接受一个函数作为输入,并返回一个新的函数,通常用于在不改变原函数的情况下添加额外的功能。
示例:简单的装饰器
def decorator(func):def wrapper():print("Something is happening before the function is called.")func()print("Something is happening after the function is called.")return wrapper
@decorator
def say_hello():print("Hello!")
say_hello()
输出:
Something is happening before the function is called.Hello!Something is happening after the function is called.
⚠️ 注意事项
-
可变对象:如果闭包中引用的对象是可以变的(如列表),那么对这个对象的任何更改都会反映在闭包中。
-
性能问题:虽然闭包很强大,但在某些情况下可能会导致性能问题或增加程序复杂度,所以应谨慎使用。
📌 总结
-
闭包是由函数及其相关引用环境组合而成的实体。
-
它允许函数“记住”并访问其定义范围内的变量,即使那个函数在其定义的作用域外被调用。
-
闭包广泛应用于各种编程模式中,如装饰器、工厂函数等。