解决Python延迟绑定问题

  介绍

小编这次要给大家分享的是解决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延迟绑定问题