Python函数嵌套及闭包

函数嵌套

函数嵌套定义

  • 指一个函数里用def语句来创建其它的函数的情况。
  • 嵌套内部函数可以访问外部函数的变量和全局变量。
  • 嵌套内部函数可以直接修改外部函数或者全局的可变变量。
  • 嵌套内部函数不能修改外部函数的不可变变量。如果要修改,在内部函数的开头加上nonlocal 变量名。
  • 嵌套内部函数修改全局不可变的变量时,需要在内部函数首行加global。
  • Locals()函数返回字典,可以看到当前函数中声明的变量或者函数有哪些。
  • Globals()看全局的变量有哪些。里面会有很多系统的东西。

函数嵌套举例

def fn_outer():
     print("fn_outer开始")
     def fn_inner():
         print("fn_inner被调用")
     fn_inner()
     fn_inner()
     print("fn_outer结束")
fn_outer()

result:
fn_outer开始
fn_inner被调用
fn_inner被调用
fn_outer结束

闭包

  • 闭包在被返回时,它的所有变量就已经固定,形成了一个封闭的对象,这个对象包含了其引用的所有外部、内部变量和表达式。当然,闭包的参数例外。
  • 针对于内嵌函数而言。
  • 内嵌函数使用了外部函数的变量。
  • 外部函数的返回值是内嵌函数对象(同时会有当时的环境)。

闭包格式

def 外部函数():
	...
	def 内部函数():
	...引用了外部函数的变量
	return 内部函数

判断一个函数是否为闭包

  • 可以通过函数名.closure 在函数为闭包时,返回一个cell ,如果不是闭包函数则返回None
# 满足闭包条件
def fn_outer():
    c = "hello"
    print("fn_outer被调用")
    def fn_inner():
        print(c)			#使用了外部函数的变量
        print("fn_inner被调用")
    return fn_inner			#返回内部函数
func = fn_outer()
print(func.__closure__)
func()

result:
fn_outer被调用
(<cell at 0x00000249919B0768: str object at 0x00000249918C75A8>,)
hello
fn_inner被调用
# 内部函数并未使用外部函数的变量,不满足闭包条件。
def fn_outer():
    c = "hello"
    print("fn_outer被调用")
    def fn_inner():
        print("hello")			
        print("fn_inner被调用")
    return fn_inner			#返回内部函数
func = fn_outer()
print(func.__closure__)
func()

result:
fn_outter被调用
None
hello
fn_inner被调用

闭包的作用

  • 记录返回闭包时外部变量的状态。
    • 当调用外部函数时,本次返回的闭包中记录了当时调用时外部变量的状态。
    • 当下一次调用时,如果外部变量发生变化,则返回闭包时又记录了新的状态。
  • 闭包是将函数内部和函数外部连接起来的桥梁。闭包函数不再受函数定义时的层级限制,它可以在其它地方调用。
  • 闭包返回时,包裹了外部函数的作用域,该函数无论在何处调用,优先使用自己外层包裹的作用域。

为什么会记录状态

  • 保存环境分析
    • func1,func2所指向的函数内存空间(parent=f1/f2)中记录了调用时fn_outer的现场。
def fn_outer(a):
    print("fn_outer被调用")
    def fn_inner():
        c = 100
        # pythontutor_hide:sum
        sum = a + c
        print("fn_inner被调用")
        return sum
    return fn_inner            #返回闭包
func1 = fn_outer(3)
func2 = fn_outer(10)
sum1 = func1()
sum2 = func2()
print(sum1, sum2) 

在这里插入图片描述

闭包的优缺点

  • 因为保存外部变量的环境,不会及时销毁,占用内存。
  • 比较简单,原来需要使用类完成的工作,使用闭包也可以。

闭包应用

  • 装饰器
  • 使一个函数内嵌套的所有函数都能为外界所调用
def 外部函数:
	...
	def 内部函数1...
	def 内部函数2...
	def 内部函数3return (内部函数1, 内部函数2)
	return 内部函数3

func = 外部函数()		# 返回内部函数3的地址
func1 = func 			# 返回(内部函数1,内部函数2)
inner_func1, inner_func2 = func1  # 得到内部函数1,2地址
inner_func1()		#调用内部函数1
inner_func2()		#调用内部函数1
<think>首先,用户的问题是:“python 嵌套函数闭包”,意思是“Python 嵌套函数闭包”。我需要用中文回答问题。 我的回答必须包括: 1. 回答问题:解释Python中的嵌套函数闭包。 2. 在回答末尾,必须提出3-5个相关问题。 3. 第一行必须是完整的“§§相关问题§§”,禁止换行分散。 4. 相关问题必须直接输出在“§§相关问题§§”之后,不能分散。 输出格式示例: - 回答内容 - §§相关问题§§ - 1. ... - 2. ... - 3. ... 现在,内容: - **嵌套函数(Nested Functions)**:在Python中,函数可以定义在另一个函数内部,这就是嵌套函数。它允许内部函数访问外部函数的局部变量。 - **闭包(Closure)**:当内部函数引用了外部函数的变量,并且这个内部函数被返回或在外部函数之外使用,它就形成了一个闭包闭包记住外部函数的状态。 我需要用中文解释: - 嵌套函数:在Python中,函数可以嵌套定义,即在一个函数内部定义另一个函数。 - 闭包:当嵌套函数引用了外部函数的变量时,它就成为一个闭包闭包保留了外部变量的值,即使外部函数已经执行完毕。 回答结构: 1. 先简要定义嵌套函数。 2. 解释闭包如何形成。 3. 可能给出一个简单的代码示例来演示闭包。 4. 然后,输出“§§相关问题§§”。 5. 列出3-5个相关问题。 相关问题必须基于用户的问题和我的回答。用户问题是关于Python嵌套函数闭包的,所以我应该提出相关的问题,比如: 1. 嵌套函数有什么作用? 2. 闭包如何避免循环引用? 3. Python闭包的常见应用场景有哪些? 4. 如何调试闭包? 5. 与全局变量相比,闭包有什么优势? 确保有3-5个问题。 最后,输出必须以“§§相关问题§§”开头,然后是编号列表。 撰写回答: - 开头:解释概念。 - 中间:提供代码示例(如示例格式所示)。 - 结束:输出相关问题。 代码示例:我需要一个Python代码来演示嵌套函数闭包。 例如: ```python def outer_function(msg): message = msg # 外部函数的变量 def inner_function(): print(message) # 内部函数引用外部变量 return inner_function # 返回内部函数,形成闭包 # 使用闭包 closure = outer_function("Hello") closure() # 输出 "Hello" ``` 然后,输出相关问题。 完整回答: 在回答中,先用中文解释,然后给出代码,最后提出相关问题。 确保所有内容符合规则。 </think>在Python中,嵌套函数指的是在一个函数内部定义另一个函数。例如,外部函数可以包含一个内部函数,后者可以直接访问外部函数的局部变量。闭包则是指当内部函数引用了外部函数的变量,并且该内部函数被返回或传递到外部作用域时,它会“记住”这些变量的值(即使外部函数已经执行完毕)。闭包常用于实现数据封装、高阶函数等功能。 以下是一个简单的代码示例,演示嵌套函数闭包: ```python def outer_func(x): def inner_func(y): # 嵌套函数定义 return x + y # 闭包:引用外部变量x return inner_func # 返回内部函数,形成闭包 # 使用闭包 closure = outer_func(10) # x被设为10 print(closure(5)) # 输出: 15(因为内部函数记住了x=10) ``` 在这个例子中,`inner_func` 引用了外部变量 `x`,当 `outer_func` 被调用后,`closure` 保留了 `x=10` 的状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值