返回顶部
首页 > 资讯 > 后端开发 > Python >python函数进阶之闭包函数
  • 641
分享到

python函数进阶之闭包函数

2024-04-02 19:04:59 641人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录闭包函数什么是闭包函数判断是否是闭包函数\__closure__cell_contents闭包函数的特点闭包函数的意义闭包函数 什么是闭包函数 如果内函数使用了外函数的局部变量,

闭包函数

什么是闭包函数

如果内函数使用了外函数的局部变量,并且外函数把内函数返回出来的过程叫做闭包,里面的内函数是闭包函数。

# 外函数 outer
def outer():
# 外函数变量 num
var = '外函数局部变量'

# 内函数 inner
def inner():
# 内函数使用了外函数的变量 num
print('内函数使用了:' + var)

# 外函数将使用了外函数的局部变量的内函数返回
return inner

# 返回出的结果就是内函数 inner,现在inner就是一个闭包函数
func = outer()

# 执行返回出的 inner 函数
func() # 内函数使用了:外函数局部变量

下面是一个复杂的版本。
inner函数返回了函数x 和 y,x 和 y是外函数的内函数,虽然覆盖了原有的外函数的局部变量,但是这两个函数本质上还是外函数的布局变量,所以外函数返回了inner,inner就是一个闭包函数。
inner返回了外函数的x和y函数,x和y函数都是用了外函数的内函数num3,外函数返回inner,inner返回了x和y,所以变相的就是外函数返回了x和y,所以x和y也是闭包函数。

# 外函数
def outer():
# 外函数的局部变量
x = 1
y = 2
num3 = 3

# 内函数 x 重名变量 x
def x():
# 调用修改了 变量 num3
nonlocal num3
num3 *= 10
print(num3)

# 内函数 y 重名变量y
def y():
# 调用修改了 变量num3
nonlocal num3
num3 += 10
print(num3)

# 内函数inner
def inner():
# 返回了同级内函数 x y
return x, y

# 外函数最终返回了 inner函数
return inner

判断是否是闭包函数

方法

作用

\__closure__

获取闭包函数使用的局部变量

cell_contents

获取单元格对象当中的闭包函数

\__closure__

可以使用这个方法判断一个函数是否是一个闭包函数,因为闭包函数必须要使用外函数的局部变量,如果返回None就说明这个函数不是闭包函数,如果返回的是一个元组,说明这是一个闭包函数,元组中有cell单元格对象,一个单元格对象表示这个闭包函数使用了几个外函数的局部变量。
拿上述版本测试

# 外函数
def outer():
# 外函数的局部变量
x = 1
y = 2
num3 = 3

# 内函数 x 重名变量 x
def x():
# 调用修改了 变量 num3
nonlocal num3
num3 *= 10
print(num3)

# 内函数 y 重名变量y
def y():
# 调用修改了 变量num3
nonlocal num3
num3 += 10
print(num3)

# 内函数inner
def inner():
# 返回了同级内函数 x y
return x, y

# 外函数最终返回了 inner函数
return inner


# 执行outer返回的结果是inner
func = outer() # func == inner

# 执行func返回的是 x y 函数
a, b = func()

# 使用__closure__测试这个几个函数是否是闭包函数
print(outer.__closure__)
print(func.__closure__)
print(a.__closure__)
print(b.__closure__)

'''
结果:除了外函数outer之外都返回了cell对象,说明inner x y 都是闭包函数
None
(<cell at 0x0000022F246AECA8: function object at 0x0000022F2466C400>, <cell at 0x0000022F247F3558: function object at 0x0000022F24850730>)
(<cell at 0x0000022F245D8708: int object at 0x00000000542280B0>,)
(<cell at 0x0000022F245D8708: int object at 0x00000000542280B0>,)
'''

cell_contents

虽然用​​__closure__​​获取到了闭包函数使用的元素,但是是以cell单元格对象的形式展示的,我们并不能看出这个使用的 元素到底是什么东西,可以使用​​cell_contents​​查看。

# 外函数
def outer():
# 外函数的局部变量
x = 1
y = 2
num3 = 3

# 内函数 x 重名变量 x
def x():
# 调用修改了 变量 num3
nonlocal num3
num3 *= 10
print(num3)

# 内函数 y 重名变量y
def y():
# 调用修改了 变量num3
nonlocal num3
num3 += 10
print(num3)

# 内函数inner
def inner():
# 返回了同级内函数 x y
return x, y

# 外函数最终返回了 inner函数
return inner


# 执行outer返回的结果是inner
func = outer() # func == inner


# 使用__closure__返回了闭包函数使用的局部变量
tup = func.__closure__

# 使用 cell_contents 查看这些局部变量都是些什么
res = tup[0].cell_contents
print(res)
res = tup[1].cell_contents
print(res)

'''
结果:可以看到inner 使用的局部变量使用外函数的内函数 x 和 y
None
<function outer.<locals>.x at 0x0000018D5A66C400>
<function outer.<locals>.y at 0x0000018D5A850730>
'''

闭包函数的特点

让我们回忆一下,函数中创建的变量是一个什么变量?是一个局部变量。
局部变量的生命周期是多久?是等局部作用结束之后就会被释放掉。

如果内函数使用了外函数的局部变量,那么这个变量就与闭包函数发生了绑定关系,就延长该变量的生命周期。实际上就是内存给它存储了这个值,暂时不释放。

下面的例子中,我们调用了函数outer并赋予了参数val的值为10,但是outer执行完之后,outer的val并没有被释放,而是被闭包函数inner延长了生命周期,所以val可以一直在inner中按照调用outer函数的时候赋予的值10进行运算。
因为内函数inner使用了外函数outer的变量val,且outer返回了inner,所以inner是一个闭包函数。因为inner是一个闭包函数,当它调用outer的变量val时就会延长val的生命周期,val就不会随着outer的调用结束而被释放
而是存储在了内存当中,当inner再次使用val时,val就会将值赋予inner。

def outer(val):
def inner(num):
return val + num

return inner

func = outer(10)
res = func(10)
print(res) # 20
res = func(20)
print(res) # 30

闭包函数的意义

闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装包保护的作用,使外部无法访问。
我们做一个模拟鼠标点击的事件,可以看得出闭包函数封装保护数据的作用。
现在只是一个普通的函数,它无法对我们使用的变量的数据进行保护,在全局中这个数据可以被随意的修改。

# 不使用闭包,当函数中调用全局变量时,外部也可以控制变量

# 全局变量
num = 0

# 点击事件
def click_num():
# 每执行一次数值 +1
global num
num += 1
print(num)

# 执行点击事件
click_num() # 1
click_num() # 2
click_num() # 3

# 在全局重新定义了num的值,num的值就被彻底的改变了,但是我们的程序的数据本不该如此。
num = 1231231

click_num() # 1231232
click_num() # 1231233
click_num() # 1231234

现在使用闭包函数对数据进行封装保护,就不能在全局中随意的修改我们使用的数据。

# 我们将需要使用的数据放在外函数中,点击事件作为内函数也放在外函数中,然后作为闭包返回。
def clickNum():
# 需要使用的数据
num = 0

# 内函数(真正执行点击事件的函数)
def inner():
# 执行点击事件
nonlocal num
num += 1
print(num)

# 作为闭包返回
return inner

# 返回闭包
click_num = clickNum() # # click_num == inner

# 执行点击事件
click_num() # 1
click_num() # 2
click_num() # 3

# 全局中修改 num 的值
num = 123412341234

# 闭包函数对数据的封装保护起到了作用
click_num() # 4
click_num() # 5
click_num() # 6

到此这篇关于python 函数进阶之闭包函数的文章就介绍到这了,更多相关Python 闭包函数内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: python函数进阶之闭包函数

本文链接: https://lsjlt.com/news/117363.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • python函数进阶之闭包函数
    目录闭包函数什么是闭包函数判断是否是闭包函数\__closure__cell_contents闭包函数的特点闭包函数的意义闭包函数 什么是闭包函数 如果内函数使用了外函数的局部变量,...
    99+
    2024-04-02
  • Python之函数进阶
    一.形参的动态参数: 动态参数,用于参数不确定时用. 格式: def fun (*args) fun(args) 1. 动态接收位置参数:动态参数必须在位置参数后.列子1.假如参数不确定时,如下的列子,每人饭量不一样,吃的种类不一样,此时...
    99+
    2023-01-30
    进阶 函数 Python
  • Python函数式编程之闭包
    -------------------------函数式编程之*******闭包------------------------ Note: 一:简介 函数式编程不是程序必须要的,但是对于简化程序有很重要的作用。 Python...
    99+
    2023-01-30
    函数 Python
  • Golang函数指针和闭包的进阶技巧
    在 go 中,函数指针是指向函数内存地址的变量,允许函数作为值处理。闭包是包含对局部变量引用的函数,可在函数执行后访问外部作用域中的数据。进阶技巧包括:使用函数指针作为回调。用闭包创建状...
    99+
    2024-04-15
    golang 闭包 指针 作用域
  • python函数的进阶
    1. 动态传参 *, ** : 形参: 聚合 位置参数* -> 元组 关键字** -> 字典 实参: 打散...
    99+
    2023-01-30
    进阶 函数 python
  • python之高阶函数和匿名函数
    map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。 1 def func(x): 2 return x*x 3 4 r = ma...
    99+
    2023-01-30
    函数 高阶 python
  • javascript之函数进阶详解
    目录函数定义方式函数的调用(6种)this指向问题严格模式高阶函数闭包递归:函数里面调用自己,需要有结束条件函数定义方式 function fn(){}//命名函数 var ...
    99+
    2024-04-02
  • 闭包函数
    目录 什么是闭包?(掌握) 两种为函数传参的方式 闭包函数的应用(掌握) 回顾: 函数对象:可以将...
    99+
    2023-01-31
    函数
  • python3--函数进阶
    例子def func(a,b,c,d,e,f,g):    passprint(func(a, b , c, d, e, f, g))如果再加30个参数呢?,在后面继续添加?有没有万能的参数,可以代表一切参数呢?*arg...
    99+
    2023-01-30
    进阶 函数
  • Python函数二(函数名,闭包,迭代器
    函数名的使用: 函数名可以作为值,赋值给变量。 函数名可以作为参数传参给函数。 函数名可以作为返回值。 函数名可以作为元素存储在容器里。 闭包:在嵌套函数内,使用外层局部变量(非全局变量)就是一个闭包,闭包可以多层嵌套。闭包的优点: ...
    99+
    2023-01-30
    函数 迭代 Python
  • Python基础之函数参数与返回值进阶
    参数作用:如果外界希望在函数内部处理数据,就可以将数据作为参数传入函数内部; 返回值作用:如果希望一个函数函数执行完成后,向外界报告函数的执行结果,就可以使用函数的返回值。 函数的返回值 进阶 利用元组返回多个函数值 可以用元组让函数返回...
    99+
    2023-01-31
    进阶 函数 返回值
  • JavaScript 闭包与高阶函数是怎样的
    JavaScript 闭包与高阶函数是怎样的,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。「JavaScript 中,函数是一等公民」,在各种...
    99+
    2024-04-02
  • Python闭包函数的用法
    本篇内容主要讲解“Python闭包函数的用法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python闭包函数的用法”吧!简而言之, 闭包的特点就是内部函数引用了外部函数中的变量。 在Pytho...
    99+
    2023-06-02
  • Python函数中的函数(闭包)用法实例
    本文实例讲述了Python闭包的用法。分享给大家供大家参考,具体如下: Python函数中也可以定义函数,也就是闭包。跟js中的闭包概念其实差不多,举个Python中闭包的例子。 def make_ad...
    99+
    2022-06-04
    函数 实例 Python
  • golang函数闭包和匿名函数之间的区别
    go 语言中的闭包和匿名函数的主要区别在于:闭包可以访问其创建范围之外的变量;匿名函数不能访问其创建范围之外的变量。 Go 语言中函数闭包和匿名函数之间的区别 闭包 闭包是一个函数,它...
    99+
    2024-04-24
    golang 闭包 匿名函数
  • Python进阶-函数默认参数(详解)
    一、默认参数 python为了简化函数的调用,提供了默认参数机制: def pow(x, n = 2): r = 1 while n > 0: r *= x n -= 1...
    99+
    2022-06-04
    进阶 详解 函数
  • 匿名函数,内置函数,闭包
    内容 匿名函数:一句话函数,比较简单的函数。 函数名 = lambda 参数 : 返回值 此函数不是没有名字,他是有名字的,他的名字就是你给其设置的变量,比如func。 func() 函数执行 lambda 是定义匿名函数的关...
    99+
    2023-01-31
    函数
  • Python 高阶函数
    高阶函数:简单来讲,一个函数可以接收另一个函数来作为参数,这样的函数称之为高阶函数 map函数 会根据提供的函数对指定序列做映射,也就是说将函数作用在指定序列 语法为 map(function,interable...) ...
    99+
    2023-01-30
    高阶 函数 Python
  • python高阶函数
    高阶函数定义:1.函数接收的参数是一个函数名;2.函数返回的是一个函数名;只要满足上述条件中的任意一个条件的函数均属于高阶函数 例如:1.函数接收的参数为函数名2.函数返回的结果为函数名3.函数接收的参数为函数名,函数返回的结果为函数名...
    99+
    2023-01-31
    高阶 函数 python
  • python闭包函数有什么用
    python中闭包函数的作用有以下几点闭包函数自带函数作用域,查找变量只会找内部函数外面的那一层。闭包函数自带延迟计算状态,可以延迟执行某个函数,需要执行时将返回结果赋值即可。闭包函数可以让函数始终保持一种状态。...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作