谈谈 Python 闭包

闭包有什么好处

Posted by mengxun on November 1, 2018

举个栗子

现在有个需求,要打印信的抬头,比方说打印 Mr Jack Miss Emily, 看看这两种实现方式 :

方法一:

def title(gender name):
	print("{gender} {name}".format(gender=gender, name=name))

>>> title("Mr", "Jack")
Mr Jack
>>> title("Mr", "Bob")
Mr Bob
>>> title("Miss", "Emily")
Miss Emily

方法二:

def title(gender):
	def output(name):
		print("{gender} {name}".format(gender=gender, name=name))
	return output
	
>>> title_mr = title("Mr")
>>> title_mr("Jack")
Mr Jack
>>> title_mr("Bob")
Mr Bob
>>> title_miss = title("Miss")
>>> title_miss("Emily")
Miss Emily

区别

第一种方法就是直接定义,但是有个缺点,就是每次都要重复的传 MrMiss。而第二种方法,也就是用了闭包的方法,会保存当前环境,把 MrMiss 提前存起来,后面就不用再反复传了。

所以说,保存上下文环境 就是闭包方便的地方。

原理

这些环境存在了哪里?

>>> title_mr.__closure__
(<cell at 0x0438D4B0: str object at 0x04379340>,)
>>> title_mr.__closure__[0].cell_contents
'Mr'

如果一个函数是闭包,那么它的__closure__ 方法会返回一个由cell对象组成的元组,而cell对象的cell_contents属性就会用来保存这些环境。

补注

其实还有另一种更方便的方式来实现闭包的效果:

from functools import partial

def title(gender name):
	print("{gender} {name}".format(gender=gender, name=name))

title_mr = partial(title, gender="Mr")
title_mr(name="Paul")

>>> Mr Paul

直接利用functools标准库,连title函数的代码都不需要改动:)。

参考:Python之禅