Python闭包是什么?简单说,闭包就是定义在一个函数内部的函数,而这个函数可以访问外部函数的变量,即使外部函数已经返回了。
def outer_func(x): def inner_func(y): return x + y return inner_func closure = outer_func(10) print(closure(5)) # 输出15,即10+5
在上面的例子中,我们定义了一个outer_func函数,它返回一个inner_func函数。当我们调用outer_func(10)时,它返回inner_func函数,并封装了x=10这一局部变量。我们将这个函数对象保存在closure变量中,这时我们就得到了一个闭包。然后我们调用closure(5),由于inner_func函数能够访问x这个变量,因此它将返回15。
闭包有什么用呢?一个常见的应用就是在装饰器中使用闭包实现函数的包装。比如我们想要给一个函数动态添加一些属性:
def add_attr(*attrs): def decorator(func): for attr in attrs: setattr(func, attr, True) return func return decorator @add_attr('is_admin', 'is_private') def my_func(): pass print(my_func.is_admin) # 输出True print(my_func.is_private) # 输出True
在上面的例子中,我们定义了一个add_attr函数,它返回一个内部函数decorator。当@add_attr('is_admin', 'is_private')装饰了my_func函数时,Python会将my_func作为参数传给add_attr函数,并将'is_admin'和'is_private'作为参数传给decorator函数。decorator函数在遍历attrs时,使用setattr函数将属性设置到my_func中,最终返回my_func本身。因此我们可以使用my_func.is_admin和my_func.is_private来访问这些属性,而这些属性是在函数定义时动态添加的。
Python闭包在多线程编程中也有广泛的应用。例如,我们想要创建一个类似于Java的Runnable接口的函数,这个函数可以在子线程中运行,并返回一个结果:
import threading def create_worker_func(func, *args, **kwargs): def worker_func(): result = func(*args, **kwargs) worker_func.result = result worker_func.result = None return worker_func def my_func(x): return x + 1 worker = create_worker_func(my_func, 5) thread = threading.Thread(target=worker) thread.start() thread.join() print(worker.result) # 输出6
在上面的例子中,我们定义了一个create_worker_func函数,它接受一个函数和可变参数,返回一个worker_func函数。当我们调用worker_func函数时,它会使用传入的函数、可变参数和关键字参数来计算结果,并将结果保存到worker_func.result属性中。由于worker_func函数是闭包,因此它可以在子线程运行,并持久保存结果。在主线程中调用print(worker.result)时,我们可以得到子线程计算的结果6。