Python装饰器实现之自由变量和闭包

装饰一词早在南北朝《玉台新咏·古诗为焦仲卿妻作》有所记载,也就是大名鼎鼎的《孔雀东南飞》,“装者,藏也,饰者,物既成加以文采也。”指的是对器物表面添加纹饰、色彩以达到美化的目的。装饰并不改变实体本身,装饰器也是如此。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的自由变量和闭包有所了解了呢。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180710G00WNQ00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券