装饰一词早在南北朝《玉台新咏·古诗为焦仲卿妻作》有所记载,也就是大名鼎鼎的《孔雀东南飞》,“装者,藏也,饰者,物既成加以文采也。”指的是对器物表面添加纹饰、色彩以达到美化的目的。装饰并不改变实体本身,装饰器也是如此。Python装饰器是一种设计模式,并不改变函数实际功能,多用在程序统计信息中,如日志打印,运行时间,信息搜集等。
要了解Python装饰器的实现原理,首先要弄清楚两个概念,自由变量和闭包,这两个概念是其实现的理论基础。那什么是自由变量呢?先看下面这个例子
其结果为:
可以看出deco函数返回的是被嵌套函数inner的函数对象,而在外部函数deco作用域中的变量authors相对内部函数inner来说就是自由变量。一般来说自由变量和闭包概念只适用于有嵌套函数存在的情况下。被嵌套函数inner可以使用外部函数deco中的变量authors,也可以不使用。当内部函数使用外部函数中定义的变量时,就构成了内部函数对自由变量的绑定,也就是闭包。那自由变量和闭包在Python源码中又是怎样的一种存在呢?
通过前面的介绍我们知道Python源码需要被编译成字节码后才能运行,函数也不例外,作为一个独立的代码块生成一个独立的字节码对象。其中有两个字段暗藏玄秘co_cellvars和co_freevars。
co_cellvars: 对外部函数而言,被嵌套的函数所引用的自由变量名
co_freevars: 对内部被嵌套而言,保存使用了的自由变量名
co_varnames: 保存自身的局部变量名
再看一个示例:
其结果为:
1为f对应的函数对象,实际上是deco函数的返回值inner函数
2为内部函数inner绑定的自由变量
3为外部函数deco所保存的内部函数绑定自由变量的信息
4为内部函数inner对自由变量改变过程的保存,这也是闭包的价值所在。
至此,是否对Python的自由变量和闭包有所了解了呢。
领取专属 10元无门槛券
私享最新 技术干货