Python闭包?

为了更好地理解python闭包,让我们首先了解什么是嵌套函数和python类。简而言之,python闭包也是一个用代码封装数据的函数。

Python嵌套函数

在另一个函数内部定义的函数称为嵌套函数。嵌套函数可以访问封闭范围的变量。

def funcOut():
   print("这是外部功能。")
   def funcIn():
      print("This function is defined inside funcOut. \nThis function(funcIn) is called\
nested function.")
   print("我们可以在这里调用嵌套函数。")
   funcIn()
print("We are in outer function.\nCalling funcOut.")
funcOut()

输出结果

We are in outer function.
Calling funcOut.
这是外部功能。
我们可以在这里调用嵌套函数。
This function is defined inside funcOut.
This function(funcIn) is called nested function.

因此,funcIn是在funcOut内部定义的嵌套函数。通过查看上面的输出,我们可以了解函数的调用顺序。

如果我们想从funcOut获得funcIn的所有功能,因为我们可能需要在上述程序中“返回funcIn”,这在python中称为闭包。

简而言之,闭包是记住其创建环境(封闭范围)的函数(对象)。

def closureFunc(start):
   def incrementBy(inc):
      return start + inc
   return incrementBy
closure1 = closureFunc(9)
closure2 = closureFunc(90)
print ('clsure1(3) = %s' %(closure1(3)))
print ('closure2(3) = %s' %(closure2(3)))

输出结果

clsure1(3) = 12
closure2(3) = 93

用closure1(3)调用变量closure1(函数类型)将返回12,而closure2(3)将返回93。虽然closure1和closure2都引用相同的函数incrementBy,但我们有两个不同的变量closure1和closure2,它们通过标识符ClosureFunc绑定在一起,从而导致不同的结果。

__closure__ attribute and cell objects

要获取更多信息,我们可以使用__closure__属性和单元格对象:

def closureFunc(start):
   def incrementBy(inc):
      return start + inc
   return incrementBy

a= closureFunc(9)
b = closureFunc(90)

print ('type(a)=%s' %(type(a)))
print ('a.__closure__=%s' %(a.__closure__))
print ('type(a.__closure__[0])=%s' %(type(a.__closure__[0])))
print ('a.__closure__[0].cell_contents=%s' %(a.__closure__[0].cell_contents))

print ('type(b)=%s' %(type(b)))
print ('b.__closure__=%s' %(b.__closure__))
print ('type(b.__closure__[0])=%s' %(type(b.__closure__[0])))
print ('b.__closure__[0].cell_contents=%s' %(b.__closure__[0].cell_contents))

输出结果

type(a) = <class 'function'>
a.__closure__ = <cell at 0x057F8490: int object at 0x68A65770>

type(a.__closure__[0]) = <class 'cell'>
a.__closure__[0].cell_contents = 9

type(b)=<class 'function'>
b.__closure__ = <cell at 0x0580BD50: int object at 0x68A65C80>

type(b.__closure__[0]) = <class 'cell'>
b.__closure__[0].cell_contents=90

从上面的输出中,我们可以看到对象的每个单元在创建时都保留了该值。