python进阶5:外层函数、内层函数和闭包

本文探讨了Python中闭包的概念及其使用注意事项,特别是当内层函数引用外层函数的变量时的情形。通过实例展示了如何避免因不当使用循环变量而导致的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  在函数内部定义的函数和外部定义的函数是一样的,只是他们无法被外部访问,例如:

def f():
    print 'f()'
    def g():
        print 'g()'
    return g #将g定义在函数f内部,防止其他代码调用g
  但是如果内部函数引用了外部函数的参数,就没法把内部函数再移到外部函数的外部,例如:

def calc_sum(lst):
    def sec_sum():
        return sum(lst)
    return sec_sum #此时sec_sum函数不能移到calc_sum的外部
  像这种内层函数引用了外层函数的变量(参数也算变量),然后返回内层函数的情况,称为闭包
  闭包的特点是返回的函数还引用了外层函数的局部变量,所以,要正确使用闭包,就要确保引用的局部变量在函

数返回后不能变。举例如下:

#希望一次返回3个函数,分别计算1*1,2*2,3*3:
def count():
    fs = []
    for i in range(1,4):
        def f():
            return i*i
        fs.append(f)
    return fs

f1, f2, f3 = count()
>>> f1() #调用的结果
9
>>> f2()
9
>>> f3()
9
  这是为什么?原因就是当count()函数返回了3个函数时,这3个函数所引用的变量 i 的值已经变成了3。由于f1、

f2、f3并没有被调用,所以,此时他们并未计算 i*i,当 f1 被调用时,i 的值已经变成了3。因此,返回函数不要

引用任何循环变量,或者后续会发生变化的变量。



### Python 函数闭包概念 在 Python 中,闭包指的是一个返回函数的过程,该过程能够记住并访问其被创建环境中的局部变量,即使这个环境在其生命周期结束之后仍然可以被访问[^1]。 闭包允许内部函数引用外部作用域的变量,并且当内部函数作为对象返回时,它会携带这些绑定在一起的数据。这种机制使得闭包非常适合用于实现数据隐藏以及构建工厂模式等功能[^3]。 ### 闭包的作用与使用场景 闭包的主要用途在于封装状态信息而不必通过显式的类定义来完成。这有助于简化某些编程逻辑,尤其是在处理回调函数或者需要保存中间计算结果的情况下非常有用[^2]。 ### 闭包语法规范 #### 基础闭包 最简单的形式如下所示: ```python def make_adder(n): def add(x): return n + x return add ``` 这里 `make_adder` 是外层函数而 `add` 则是内嵌于其中的另一个函数。调用 `make_adder` 后得到的结果实际上就是指向了 `add` 的引用,此时即便已经离开了 `make_adder` 所处的作用范围,所获得的新函数依旧能正常工作因为它们保留着对外部参数 `n` 的记忆。 #### 带有参数操作的闭包 更复杂的例子可能涉及多个层次上的嵌套结构或是传递额外参数给最终形成的闭包实例: ```python def create_counter(start=0, step=1): count = start def counter(): nonlocal count current = count count += step return current return counter ``` 此段代码展示了如何利用闭包特性去维护计数器的状态变化,同时支持自定义初始值(`start`) 增量 (`step`) 参数设置。 ### 实际应用案例 考虑这样一个需求——我们需要编写一段程序用来记录某个特定事件发生的次数。借助闭包我们可以轻松达成目标: ```python def event_tracker(event_name="default"): times_occurred = 0 def track_event(): nonlocal times_occurred times_occurred += 1 print(f"{event_name} occurred {times_occurred} time(s).") return track_event track_login_attempts = event_tracker("Login Attempt") for _ in range(5): track_login_attempts() ``` 上述脚本每次调用 `track_login_attempts()` 都会在控制台打印当前登录尝试的具体情况,而且由于采用了闭包技术所以无需担心其他地方可能会干扰到我们的统计逻辑。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值