Python嵌套函数\闭包

本文深入探讨了Python中函数嵌套的概念,通过具体实例展示了内部函数如何访问外部函数的作用域,以及如何通过声明全局变量让外部函数访问内部变量。
Python中一个与众不同的语法就是可以嵌套函数,所谓嵌套,并不像其他语言中的在一个函数中调用另一个函数,而是在定义一个函数的时候,函数体里还能定义另一个函数。
内函数可以访问外函数的作用域,这就是《Python基础教程》P105里“它带着它的环境(和相关的局部变量)”及“由于Python的嵌套作用域,来自外部作用域的这个变量,稍后会被内层函数访问”。但是外部函数不能访问内部函数的作用域。

下面用编程实例来详细说明:
#在func_1()中定义了func_2(),func_2()中又定义了func_3()
def func_1():
    x1 = "func_1"
    #print("x1 = %s,x2 = %s,x3 = %s" % (x1,x2,x3))运行此句出现错误
    print("In func_1: x1 = %s" % x1)
    
    def func_2():
        x1 = "func_1_redefined"
        #将X2声明为全局变量,这样才可以在其外层函数func_1()中使用
        global x2 
        x2 = "func_2"
        print("In func_2: x1 = %s,x2 = %s" % (x1,x2))

        def func_3():
            x3 = "func_3"
            print("In func_3: x1 = %s,x2 = %s,x3 = %s" % (x1,x2,x3))

        return func_3()
    
    #调用func_2()使global x2被定义使用
    func_2()
    print("In func_1,again: x1 = %s,x2 = %s" % (x1,x2))

下面是运行结果(环境是Python 3.3.0): Python征途_第2记——嵌套函数/嵌套作用域/闭包(closure)

程序分析:
1)1只能访问自己定义的变量,2可以访问1和2中定义的变量但不能访问3中的变量,3可以访问所有变量;所以内部函数可以访问其外部函数的作用域,但是外部函数不能访问内部函数的作用域。
2)如果2中的变量被1访问到,可以用gloabl对其声明,但在使用前必须调用2。
3)若1,2中都有x1,则3中访问到的是2中的x1(离它最近的作用域中的x1),1中的x1不变(不被重新赋值)。

我的总结:
当函数实现的功能比较复杂,代码量比较大时,可以对函数进行分片,在这个函数的内部定义实现某一功能的函数,这样做的好处是代码易懂,并且可以对一部分变量封装,避免对变量的误操作。
书上说“存储子封闭作用域的行为叫做闭包”。

转载地址:http://blog.sina.com.cn/s/blog_4a8fa26101019fny.html


Python,函数嵌套,到底是个什么东东?

很少有人用,但是,有时确实会用:

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. def multiplier(factor):  
  2.     def multiplyByFactor(number):  
  3.           return number*factor  
  4.     return multiplyByFactor  

python 程序,一个函数在另外一个函数的里面,外层的函数返回的是里层函数。也就是函数本身被返回了,返回的是函数(听起来和C语言的一些东东相似)。

注意,返回的函数还可以访问它的定义所在的作用域,也就是它带着它的环境信息奥。


看看下面的用法,就会有被水浇的感觉了:

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. >>>double = multiplier(2)  
  2. >>>double(5)  
  3. 10  
  4.   
  5. >>>triple=multiplier(3)  
  6. >>>triple(3)  
  7. 9  
  8.   
  9. >>>multiplier(5)(4)  
  10. >>>20  

每次调用外层函数,它内部的函数都会被重新绑定,factor变量每次都有一个新的值。


以上内容摘抄自《python基础教程》

转载地址:http://blog.csdn.net/shanzhizi/article/details/46385601


<think>首先,用户的问题是:“我想了解Python匿名函数嵌套闭包相关知识 请问Python匿名函数嵌套闭包介绍”。所以,我需要介绍Python匿名函数嵌套闭包。 从系统级指令: - 所有行内数学表达式必须使用$...$格式:但这里涉及编程,可能没有数学表达式,除非是示例代码。我会避免数学表达式,除非必要。 - 独立公式用$$...$$:同样,可能不需要。 - LaTeX语法正确:在代码块中,我会确保Python代码正确。 - 使用中文回答。 - 生成相关问题:在回答末尾添加相关问题。 - 回答中引用的段落末尾添加引用标识:我需要引用提供的参考文献。用户提供了引用[1]到[5],我需要参考这些来构建答案。 引用内容: - [1]:谈闭包的应用:数据封装、装饰器、回调函数;注意事项:延迟绑定,可能导致内存泄漏。 - [2]:闭包函数里面嵌套函数的外层函数返回里层函数函数名;是概念,不是函数类型;可以得到外层函数的局部变量。 - [3]:嵌套函数的使用场景:减少多次调用的开销;闭包。 - [4]:匿名函数基于lambda表达式;定义没有名字的函数;示例。 - [5]:参数处理;分拆参数;匿名函数。 用户的问题焦点:匿名函数嵌套闭包。所以,我需要结合匿名函数(lambda)和闭包的概念。 关键点: - **匿名函数**:在Python中,使用lambda关键字定义,如:lambda x: x+100。 - **嵌套函数**:在一个函数内部定义另一个函数。匿名函数可以是嵌套的? - **闭包**:当一个嵌套函数引用了外部函数的变量,并且外部函数返回内部函数时,形成一个闭包。 现在,对于匿名函数嵌套闭包: - 匿名函数本身可以是闭包的一部分。例如,在外部函数内部定义一个匿名函数,并将其返回。 - 引用[4]中提到匿名函数:lambda表达式定义函数。 - 引用[2]和[3]讨论闭包:涉及嵌套函数。 因此,我需要解释: 1. 什么是匿名函数(lambda函数):简洁定义函数。 2. 嵌套函数:在函数内部定义函数。 3. 闭包嵌套函数捕获外部变量的状态。 4. 如何匿名函数用于嵌套和创建闭包:例如,在外部函数中定义匿名函数并返回它。 结构回答: - 先介绍匿名函数。 - 然后介绍嵌套函数。 - 接着讨论闭包。 - 最后结合它们:匿名函数闭包中的应用。 - 提供代码示例。 - 引用相关引用。 代码示例: - 从引用[4]:匿名函数示例:lambda x: x+100。 - 创建一个闭包使用匿名函数:例如,外部函数返回一个lambda函数,该lambda函数捕获外部变量。 示例大纲: - 定义外部函数 def outer(x): - 内部使用匿名函数:lambda y: x + y - 返回这个匿名函数 - 然后调用:closure = outer(10),然后 closure(5) 应该返回15。 确保引用: - 当我提到概念时,添加引用标识,如[^2]或[^4]。 相关问题生成: - 在末尾,生成3-5个相关问题,基于主题。 完整回答结构: 1. **介绍匿名函数**:简述lambda函数。 2. **介绍嵌套函数**:函数内部定义函数。 3. **介绍闭包**:嵌套函数捕获外部变量。 4. **匿名函数闭包中的使用**:示例代码。 5. **注意事项**:如延迟绑定或内存泄漏。 6. **相关问题**。 使用中文。 </think>### Python匿名函数嵌套闭包介绍 在Python中,匿名函数(通常使用lambda表达式定义)是一种简洁定义函数的方式,无需显式指定函数名。嵌套函数则是指在另一个函数内部定义的函数,而闭包是一种特殊机制,允许内部函数捕获并访问外部函数的局部变量,即使外部函数已完成执行。这种组合在数据封装、延迟计算和回调函数等场景中非常有用[^2][^4]。下面我将逐步解析匿名函数嵌套闭包相关知识。 #### 1. **匿名函数基础** - 匿名函数使用lambda关键字定义,语法为:`lambda 参数: 表达式`。它没有函数名,常用于简化代码或作为参数传递给高阶函数(如map、filter)。 - 示例:`lambda x: x + 100` 定义了一个匿名函数,它接收参数x并返回x+100的结果[^4]。 - 特性:匿名函数只能包含单个表达式,不能包含复杂语句(如循环或if-else分支)。它适合于简单操作,但可读性较低。 #### 2. **嵌套函数** - 嵌套函数是指在外部函数内部定义的另一个函数(可以是命名函数或匿名函数)。这种方式有助于封装逻辑和减少重复代码。 - 使用场景:当需要多次调用某个逻辑时,外部函数可以处理共享资源(如变量初始化),而内部函数负责具体计算,从而提升效率[^3]。 - 示例:外部函数定义匿名函数作为内部函数。 ```python def outer_func(x): # 外部函数局部变量 multiplier = 10 # 内部匿名函数嵌套) inner_lambda = lambda y: x * multiplier + y return inner_lambda # 返回匿名函数 # 调用外部函数,返回内部匿名函数 closure = outer_func(5) # x固定为5,multiplier为10 print(closure(3)) # 输出: 5*10 + 3 = 53 ``` 在此示例中,`inner_lambda`是一个嵌套匿名函数,它访问外部函数的局部变量`x`和`multiplier`。 #### 3. **闭包机制** - 闭包(closure)是指嵌套函数(如匿名函数)捕获并记住外部函数的局部变量状态,即使外部函数已执行结束。闭包的关键特征是: - 外部函数返回内部函数(可以是匿名函数)。 - 内部函数引用外部函数的变量。 - 闭包不是函数类型,而是一种特殊调用模式,类似于递归[^2]。 - 闭包的作用:作为数据封装工具(隐藏实现细节)、实现装饰器或回调函数(携带额外上下文)[^1][^4]。 - **匿名函数闭包示例**:外部函数返回一个匿名函数,该匿名函数捕获外部变量。 ```python def create_adder(a): # 返回匿名函数闭包 return lambda b: a + b # 匿名函数捕获外部变量a # 创建闭包实例 add_five = create_adder(5) # a固定为5 print(add_five(3)) # 输出: 8(5+3) print(add_five(10)) # 输出: 15(5+10) ``` 在此代码中: - `create_adder`是外部函数,局部变量`a`被匿名函数捕获。 - 匿名函数`lambda b: a + b`形成闭包,保留变量`a`的值(5),即使`create_adder`已执行完毕。 - 闭包允许匿名函数携带状态信息(如`a`),类似于数据封装[^1]。 #### 4. **嵌套匿名函数闭包的注意事项** - **延迟绑定(late binding)**:闭包中的变量在调用时才解析,而非定义时。这可能导致意外行为,尤其在循环中定义闭包时[^1]。 - 问题示例: ```python closures = [] for i in range(3): closures.append(lambda x: x + i) # 所有闭包共享同一个i print(closures[0](10)) # 期望输出10+0=10,但实际输出10+2=12(i最终为2) ``` - 解决方案:使用默认参数或外部封装固定值。 ```python for i in range(3): closures.append(lambda x, i=i: x + i) # 绑定当前i值 ``` - **内存泄漏风险**:闭包会保留外部变量引用,即使不再需要,可能导致内存无法释放。建议在不再使用时显式解除引用(如设置`closure = None`)[^1]。 - **应用场景**: - **装饰器**:装饰器本质是闭包,匿名函数常用于简化装饰器逻辑[^1][^4]。 - **回调函数**:匿名函数闭包可传递额外数据给事件处理器[^1]。 - **高性能计算**:嵌套匿名函数减少重复初始化开销[^3]。 #### 5. **总结** 匿名函数嵌套闭包结合了lambda表达式的简洁性与闭包的封装能力,适用于状态管理、代码复用和高阶函数设计[^2][^4]。但需注意延迟绑定和内存问题,以确保代码健壮性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值