当前位置: 首页 > 图灵资讯 > 行业资讯> Python之初识闭包函数

Python之初识闭包函数

发布时间:2025-10-24 16:05:29

Python中的闭包函数

通常定义函数是这样的:

deffoo():
pass

事实上,函数也可以嵌套在函数编程中,如下:

deffoo():
print("helloworldinfoo")

defbar():
print("helloworldinbar")

当我们调用foo函数时,执行结果会是什么样子??

helloworldinfoo

如上所示,foo函数的第一层函数只会执行,bar函数不会执行。为什么?

事实上,无论函数写在哪一部分,它都只定义了一个函数,只有当函数被调用时,函数中的句子才会被执行。

在上面的例子中,虽然bar函数是在foo函数内部定义的,但它没有被执行,因此bar函数不会被执行。

这样,定义函数内部的函数没有效果吗??事实并非如此。

以下例子为例,将bar函数作为一个值返回到foo函数,以查看执行过程:

deffoo():
print("helloworldinfoo")

defbar():
print("helloworldinbar")
returnbar
f1=foo()
print(f1)

此时,由于bar函数作为返回值返回到foo,因此foo函数的执行结果具有返回值。此时,定义一个变量f1来接收foo函数的执行返回结果,然后打印f1。

返回结果如下:

helloworldinfoo
<functionfoo.<locals>.2941A60000000000>

可以看出,foo函数中定义的print语句首先打印出来,然后打印出foo函数中包含的bar函数的内存地址。既然是函数的内存地址,当然可以加括号来执行这个函数。

deffoo():
print("helloworldinfoo")
defbar():
print("helloworldinbar")
returnbar
f1=foo()
f1()

此时,该代码的执行结果如下:

helloworldinfoo
helloworldinbar

两个print语句都打印出来了。

在上面的例子中,首先定义函数foo,然后嵌套在foo函数中定义函数bar,然后返回函数bar的函数名,这是闭包函数的定义。事实上,闭包的定义是一个函数嵌套在一个函数中。

看下面的代码:

deffoo():
print("helloworldinfoo")
name="python"
defbar():
print(name)
print("helloworldinbar")
returnbar

f1=foo()
f1()

在上面的例子中,将变量name定义为外层函数,然后将变量name打印在内层函数中。

此时,执行上述代码。打印name变量时,您将首先在bar函数中找到name变量,但bar函数中没有name变量。此时,根据python搜索变量的LEGB规则,您将继续在bar函数的外层搜索name变量。此时,您可以找到name变量,因此在这里打印的foo函数中定义的name值。

执行上述代码,打印结果如下:

helloworldinfoo
python
helloworldinbar

请记住,内层函数引用外层函数的局部变量是非常重要的。

在下面的例子中分析程序的执行过程:

首先运行foo函数,foo函数的执行结果是返回bar的函数名,此时将foo函数的执行结果定义为变量f1,

因此,此时f1等于bar函数的内存地址,然后f1加括号运行表示bar函数运行。

在执行bar函数的过程中,bar函数访问了外foo函数中定义的变量,这是一个典型的闭包函数。

使用封闭函数有什么好处??在上面的例子中,f1的值是bar函数的内存地址,f1加括号操作是bar函数的操作。

由于F1是一个全球变量,这意味着F1函数可以在整个程序的任何位置运行,然后定义一个函数,并在该函数内部调用F1函数,

deffoo():
print("helloworldinfoo")
name="python"

defbar():
print(name)
print("helloworldinbar")
returnbar

f1=foo()

deffunc():
name="aaaaa"
f1()

func()

对程序执行过程进行分析:

1.运行func函数时,程序将首先在内存中申请一个空间来保存name变量值,然后运行f1函数。f1是全球定义的变量,因此您必须找到f1函数的内存地址。

2.f1加括号运行是在执行一个闭包函数时,在这个闭包函数中引用name变量。

3.name的变量已经在bar函数的外部定义,因此在func函数中调用f1函数,即bar函数时,引用的变量仍然是func函数内部定义的name变量,而不是func函数内部定义的name变量。

4.由于f1函数的内部已经包含了name函数的值,即使在func函数中也定义了name的变量,程序执行的结果仍然打印了fooo函数内部定义的name值。

相关建议:Python视频教程

程序执行结果:

helloworldinfoo
python
helloworldinbar

如何验证一个函数是闭包函数?首先,闭包函数有一个独特的属性:closure。

在上面的例子中,打印F1的__closure__属性。

deffoo():
name="python"

defbar():
print(name)
print("helloworldinbar")
returnbar

f1=foo()
print(f1.__closure__)

打印结果如下:

(<cellat00000000000001DF57:Strobjectat000000001E79688>,)

能看见____closure_____________________________closure__返回元组元素的cell_contents方法打印name变量值。

deffoo():
name="python"

defbar():
print(name)
print("helloworldinbar")
returnbar

f1=foo()
print(f1.__closure__[0].cell_contents)

打印结果如下:

python

可以看出,程序已经打印出name变量值,即然__closure__的返回结果是一个元组,所以这个元组必须包含多个值,看下面的例子。

在foo函数中定义多个变量,然后在bar函数中打印几个变量值,然后运行此闭包函数,打印闭包函数__closure__方法。

deffoo():
print("helloworldinfoo")
name1="python1"
name2="python2"
name3="python3"
name4="python4"

defbar():
print(name1)
print(name2)
print(name3)
print(name4)
print("helloworldinbar")
returnbar

f1=foo()
print(f1.__closure__)

程序执行结果:

(<2145708,cellat000000000:C926000000,strobjectat00000021C92000>,
<0000000,00000,00000,45A08:Bjectat000000000000021C93>,
<21457688,cellat000000000000:Strobjectat00000000295BE3000000>,
<2145C185C18,cellat000000000:strobjectat000000000000000002968>)

由于在foo函数中定义了四个变量,并且在bar函数中引用了这四个变量,因此打印这个封闭函数的__closure__方法,返回元组中有4个元素。

这四个字符串对象的值现在可以单独打印回元组。

deffoo():
name1="python1"
name2="python2"
name3="python3"
name4="python4"

defbar():
print(name1)
print(name2)
print(name3)
print(name4)
print("helloworldinbar")
returnbar

f1=foo()
print(f1.__closure__[0].cell_contents)
print(f1.__closure__[1].cell_contents)
print(f1.__closure__[2].cell_contents)
print(f1.__closure__[3].cell_contents)

程序执行结果:

python1
python2
python3
python4

所以还有最后一个问题,那就是闭包函数的内层函数必须返回吗??

以下示例:

deffoo():
name="python1"

defbar():
print(name)
print(bar.__closure__)

foo()

定义了嵌套函数,然后嵌套函数的内层函数没有返回,而是直接打印了内层函数__closure方法,然后直接调用外部函数。

程序执行结果:

(<000000,cellat000002157080:D9688,strobjectat000000000021D9688>,)

内层函数引用的变量对象仍然打印出来,说明闭包函数的内层函数必须返回。

闭包函数的内层函数能调用全局变量吗??

将外层函数内部定义的变量改为全局变量,然后在内层函数中引用。

name="python1"

deffoo():
defbar():
print(name)

print(bar.__closure__)

f=foo()
print(f)

程序执行结果:

None
None

可以看出,程序的执行结果是两个None,嵌套函数的内层函数__closure__函数值为none,说明foo函数内嵌套函数bar调用的全局变量不成功,所以上面的例子不是封闭函数。

关于闭包函数的一些总结:

闭包的定义如下:

(1)函数内部定义的函数称为内部函数。

(2)内部函数调用外部函数的局部变量。

(3)即使内部函数返回,局部变量也可以使用。

(4)闭包函数的内层函数通常会返回到外部函数。

(5)闭包函数的外部函数可以在任何地方调用,而不再受函数定义时级别的限制。

闭包函数的作用

1.闭包函数自带函数作用域

在函数执行过程中,正常意义上的函数搜索变量的顺序是逐层向外搜索,符合LEGB(Local->Enclose->Global->Built in)法则的,

然而,对于闭包函数,搜索变量只会找到内部函数外的一层,因为闭包函数本身有一层功能域,因此符合要求"闭包"两个字的意思。

2.延迟计算(又称惰性计算)

看下面的例子

deffunc():
name="python"
defbar():
print(name)
returnbar

f=func()
print(f.__closure)

在上面的例子中,foo()函数的返回结果是一个包含自己状态的函数,但实际上这个函数并没有执行,

以后想要执行这个自带状态的函数时,可以执行func()返回结果赋值的变量加括号。

3.闭包可以用来保持一个函数的一种状态。

例子:

name="python"

deffunc():
print("Ilike%s"%name)

func()

上述代码执行结果将打印一行:"I like python"

但我们知道,如果在不同的地方调用func函数,打印结果可能会有所不同,所以如果我想在任何地方调用func函数,打印结果都是"I like python"当时,可以使用闭包。

defunc1():

name="python"
deffunc():
print("Ilike%s"%name)
returnfunc

func=func1()
func()

如上图所示,一层函数func1包含在func函数外,执行func1函数,然后将func1函数的返回结果赋值给func这个变量。

此时func是一个闭包函数,func函数加括号即可执行。

此外,我们必须知道func函数的执行结果将在此时打印"I like python"无论func函数在程序的哪个位置被调用,执行结果都是一样的。

相关文章

Python之初识闭包函数

Python之初识闭包函数

2025-10-24
Python如何将图片转换成字符

Python如何将图片转换成字符

2025-10-24
python如何通过日志分析加入黑名单

python如何通过日志分析加入黑名单

2025-10-23
Python之classmethod和staticmethod的区别

Python之classmethod和staticmethod的区别

2025-10-23
Python3中的数字(Number)

Python3中的数字(Number)

2025-10-23
Python如何使用数据库的连接池

Python如何使用数据库的连接池

2025-10-23