小编这次要给大家分享的是解决Python延迟绑定问题,文章内容丰富,感兴趣的小伙伴可以来了解一下,希望大家阅读完这篇文章之后能够有所收获。
延迟绑定出现在闭包问题中。下面我们看一个闭包的例子:
def (n): def mul (x): 返回n * x 返回mul 双=gen_mul (2) doubled_value=https://www.yisu.com/zixun/double (6)
可以看出满足闭包的几点:
- <李>有内部函数李> <李>内部函数引用了外部函数中的自由变量李> <李>内部函数被返回
李,>
闭包的优点:
- <李>可以避免使用全局变量李> <李>可以持久化变量,达到静态变量的作用
李,>
闭包的缺点:
- <李>可能会消耗大量的内存李> <李>可能会导致内存泄漏李>
当然缺点可以通过人为避免。
现在我们来看看另一个会引出延迟绑定的例子:
def乘数(): 返回(λx:我* x范围(4)) print ([m (2) m的乘数()))# (6 6 6 6)
上边的例子会输出[6、6、6、6],而不是我们预期的[0、2、4、6]。
这就是延迟绑定导致的结果。具体过程我们可以来分析下:
执行第三行时,会先执行乘数函数,然后执行函数中的列表解析式。在每一次迭代的时候都会生成一个匿名函数(这里只是定义)作为元素,然后回到第三行,遍历返回的列表中的匿名函数,传入参数2并执行。此时函数类似于这样:
def无名(x):
引用>
返回我* x
我们知道Python查找变量的作用域链的顺序依次为LEGB:
局部变量(L)→外部函数中的局部变量(E)→全局变量(G)→内置变量(B)
非常重要的一点我们需要知道:Python的作用域在编译时就已经形成了,而不是在运行时,函数的作用域与其被调用的位置无关。
那么在本例中,上面的无名函数体中的我从何而来呢?当然首先会到乘数函数的局部变量中去寻找。此时我的值已经为3,所以出现这种让人“费解”的现象。
那么现在我们既然已经知道了原因,那么要怎样解决呢?
我们可以将迭代的我值直接注入到匿名函数的函数体中,这里给出两种方法:
通过为参数设置默认值,这是因为在编译时就会计算确定默认值:
def multipliers_ch2 ():
引用>
返回(λm x=我:m * x范围(4)]我的
通过内置函数部分:
从functools导入部分 def multipliers_ch3 (): 返回(部分(λm x: m * x,我)我的范围(4)]利用生成器的延迟计算:
def multipliers_ch4 (): 米的范围(4): 收益率λx: m * x部分及生成器的内容会在以后分享。
运行结果
打印([m(2)的m multipliers_ch2 ())) # (0、2、4、6)
引用>
打印([m(2)的m multipliers_ch3 ())) # (0、2、4、6)
打印([m(2)的m multipliers_ch4 ())) # (0、2、4、6)
注:
自由变量:指未在本地作用域中绑定的变量,我们可通过访问函数的代码属性进行查看:
fun.code。co_freevars
看完这篇关于解决Python延迟绑定问题的文章,如果觉得文章内容写得不错的话,可以把它分享出去给更多人看到。
解决Python延迟绑定问题