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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值