参考资料 http://python.jobbole.com/81683/
Python的命名空间
任何一个变量在创建时都会创建在自己的命名空间内,如果自己的命名空间内不含有这个名字,就会创建一个新的,而不是覆盖上层的命名空间,在访问时,如果自己的命名空间内没有,则访问上层的。Python的闭包
任何函数都是对象。可以创建一个待调用的对象。如果创建一个待调用的函数,其内部过程使用了一个局部变量,此时设计到了闭包:嵌套定义在非全局作用域里面的函数能够记住它在被定义的时候它所处的封闭命名空间。
通俗的说:子函数可以使用父函数中的局部变量,这种行为就叫做闭包。
闭包细节之C++与Python
一般情况下,大部分语言的父函数的局部变量,会随着父函数退出而结束生命周期。此时lambda函数,或者函数对象的调用中,如果引用了父函数的局部变量,就会出现问题。如果定义lambda或函数对象在定义的过程中,能够记住当前的命名空间,就是闭包。可是C++中,局部变量的生命周期规定是和父函数一样,怎么办?使用mutable修饰变量,该变量的生命周期就会变得和函数对象和lambda表达式一样长,否则捕捉这些变量时可能就会有问题。而Python会将闭包中的对象都捕捉到,不让其释放。直到函数对象回收为止。装饰器
有的时候我们需要对函数做一些改装,而这些改装的工作几乎类似。例如,我们需要对函数的运行时间进行计算,此时,我们需要在所有函数开始和结尾加上一个时间戳。然后在函数结束时进行打印。或者,我们需要对参数和返回值进行校验。当然我们可以在所有函数开始和结束的时候调用校验函数。
装饰器可以完成这样的功能。例如我们有一个函数
def func():
time.sleep(1)
使用另一个返回带有闭包的函数对象的函数来完成这样的功能
def addTimePrint(func):
def retFuncObj(*args, **kwargs):
starttime = time()
func(*args, **kwargs)
print(time() - starttime)
return retFuncObj
然后我们需要把新的func函数替换掉。
func = addTimePrint(func)
Python提供了一个语法糖,在定义了addTimePrint之后,使用@addTimePrint就可以完成函数的定义和装饰
@addTimePrint
def func():
time.sleep(1)