学习Python的单例实现的时候,遇到了下面这样的代码。很不理解为什么局部变量 _instance没有重新初始化。后来看到有人说这是闭包,于是又去了解了下
闭包。没想到闭包竟然是编程语言中一个通用的概念,于是深入研究了下。
def singleton(cls): _instance = {} def inner(): if cls not in _instance: _instance[cls] = cls() return _instance[cls] return inner @singleton class Cls(object): def __init__(self): pass cls1 = Cls() cls2 = Cls() print(id(cls1) == id(cls2))
闭包是为了在函数是一等公民的编程语言中实现词法作用域的名称绑定的一种机制---翻译自Wiki。估计这么说也没有人能看的懂。先看看一个Python闭包代码:
def f(x): def g(y): return x + y return g # Return a closure. a = f(1) #创建闭包 assert a(5) == 6
bar函数引用外层的foo的变量x,这个x的词法作用域就是bar函数。但是bar中并没有定义变量x,解释器只能向上找外层函数(enclosing function)的x。创建闭包的时候,会给X绑定一个值。这就是定义的由来。可见一个完整的闭包由一个函数和这个函数所处的上下文构成,这个上下文包含了对闭包函数内部自由变量的定义,如图2-1。这个自由变量的生命周期是从创建闭包开始到销毁闭包结束,不同于一般函数局部变量的作用域。f(x) = x + y 中的变量y就是一个自由变量,这个变量的值是多少不是在函数f中给出的。
1.https://zhuanlan.zhihu.com/p/37534850
2.https://en.wikipedia.org/wiki/Closure_(computer_programming)
3.https://zhuanlan.zhihu.com/p/37534850
4.https://goldengrape.github.io/posts/python/Lambda_Tutorials/mian-xiang-yan-ke-yi-sheng-de-lyan-suan-ru-men-jiao-cheng-3/ 很好的lambda演算入门,看完就明白什么是自由变量和绑定变量了
5.https://en.wikipedia.org/wiki/Free_variables_and_bound_variables
6.https://en.wikipedia.org/wiki/Name_binding
7.https://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scope 解释了什么是词法作用域