Python - 闭包:初学者指南
你好,有抱负的Python程序员!今天,我们将开始一段激动人心的旅程,进入闭包的世界。如果你之前从未听说过这个术语,请不要担心——在本教程结束时,你不仅会理解闭包是什么,而且还能在自己的代码中创建和使用它们。那么,让我们开始吧!
什么是闭包?
想象你有一个神奇的盒子,即使在关闭它之后,它也能记住事情。在编程中,闭包本质上就是这样一种神奇的盒子!在Python中,闭包是一个函数对象,它能够记住封闭作用域中的值,即使它们不在内存中。
听起来很困惑?让我们来分解一下:
- 它是另一个函数内部的函数。
- 它可以访问外部函数的变量。
- 即使外部函数执行完成,它也会记住这些变量。
把它想象成一种创建功能小包的方式,这个小包装载着它自己的私有数据。很酷,对吧?
嵌套函数
在我们深入探讨闭包之前,先来谈谈嵌套函数。这些只是定义在其他函数内部的函数。这里有一个简单的例子:
def outer_function(x):
def inner_function(y):
return x + y
return inner_function
result = outer_function(10)
print(result(5)) # 输出:15
在这个例子中,inner_function
嵌套在outer_function
内部。内部函数可以访问外部函数的x
参数。这是理解闭包的一个关键概念。
变量作用域
要真正掌握闭包,我们需要理解Python中的变量作用域。有三种作用域:
- 局部作用域:在函数内部定义的变量
- 封闭作用域:嵌套函数外部函数中的变量
- 全局作用域:在模块顶层定义的变量
以下是一个示例来说明:
x = "我是全局的!" # 全局作用域
def outer():
y = "我来自外部!" # 封闭作用域
def inner():
z = "我是本地的!" # 局部作用域
print(x, y, z)
inner()
outer()
当你运行这段代码时,你会看到打印出所有三个变量。inner
函数可以访问这三个作用域中的所有变量!
创建闭包
现在我们理解了嵌套函数和变量作用域,让我们来创建一个闭包。当嵌套函数引用其封闭作用域中的值时,就会发生闭包。以下是一个例子:
def multiply_by(n):
def multiplier(x):
return x * n
return multiplier
times_two = multiply_by(2)
times_three = multiply_by(3)
print(times_two(5)) # 输出:10
print(times_three(5)) # 输出:15
在这个例子中,multiply_by
是我们的外部函数,multiplier
是我们的内部函数。当返回multiplier
时,魔法就发生了——即使multiply_by
执行完成,它也会记住n
的值。这就是一个闭包!
让我们逐步分解:
- 我们定义了
multiply_by
,它接受一个参数n
。 - 在
multiply_by
内部,我们定义了multiplier
,它接受一个参数x
。 -
multiplier
使用它自己的参数x
和外部函数的n
。 - 我们从
multiply_by
返回multiplier
。 - 当我们调用
multiply_by(2)
时,它返回一个总是将其输入乘以2的函数。 - 同样,
multiply_by(3)
返回一个总是将其输入乘以3的函数。
这就是闭包的力量——它们可以即时创建专业的函数!
nonlocal
关键字
有时,你可能会想在内部函数中修改封闭作用域的变量。Python提供了nonlocal
关键字来实现这一点。以下是一个例子:
def counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment
my_counter = counter()
print(my_counter()) # 输出:1
print(my_counter()) # 输出:2
print(my_counter()) # 输出:3
在这个例子中,increment
是一个闭包,它记住并修改封闭作用域中的count
变量。nonlocal
关键字告诉Python,count
不是局部变量,而是封闭作用域中的变量。
闭包的实际用途
闭包不仅仅是炫酷的技巧——它们有实际的应用!以下是一些例子:
- 数据隐藏和封装
- 创建函数工厂
- 实现装饰器
让我们看一个现实世界的例子。想象你正在为一家在线商店创建一个折扣系统:
def create_price_adjuster(discount):
def adjust_price(price):
return price * (1 - discount)
return adjust_price
black_friday_sale = create_price_adjuster(0.2) # 20%折扣
cyber_monday_sale = create_price_adjuster(0.15) # 15%折扣
original_price = 100
print(f"黑色星期五价格:${black_friday_sale(original_price)}")
print(f"网络星期一价格:${cyber_monday_sale(original_price)}")
这段代码为不同的销售活动创建了不同的定价函数,所有这些都使用了相同的基函数。这就是闭包的力量!
总结
恭喜!你刚刚了解了Python的一个更高级的特性。让我们回顾一下我们所学的内容:
概念 | 描述 |
---|---|
闭包 | 记住封闭作用域中的值的函数 |
嵌套函数 | 定义在另一个函数内部的函数 |
变量作用域 | 变量的可见性(局部,封闭,全局) |
nonlocal |
修改封闭作用域中的变量的关键字 |
请记住,像任何强大的工具一样,闭包应该谨慎使用。它们在执行某些任务时很棒,但过度使用它们可能会使代码更难理解。练习,实验,很快你就能像Python高手一样挥舞闭包了!
编码愉快,请记住——在Python中,就像在生活中一样,内在(函数)才是最重要的!
Credits: Image by storyset