python 延迟绑定

时间:2023-03-08 17:24:28
python 延迟绑定

def multipliers(n):

  funcs = []

  for i in range(n):

    def f(x):

      return x * i

    funcs.append(f)

  return funcs

g0, g1, g2, g3 = mutipliters(4)

print(g0(10))                 # 30

print(g1(10))                 # 30

print(g1(10))                 # 30

print(g1(10))                 # 30

被同学问道如上问题, 为什么,生成的4个函数.最终返回的值一样.

查看了四个函数的内存地址,是不同的内存地址.

说明四个函数,是不同的函数.不是因为函数明重复,导致了覆盖的问题

那就是说明 i 值的问题.

打印出四个函数调用时,i 的值,发现都是3,

但是, 没有循环发生,所以是直接访问了i的值

于是查看了 四个函数掉用时, i 的id, id(i)的值相同. 发现是同一个内存地址.

也就是说函数调用的时候,是动态取 i 所在地址里面的值, 而在生成函数range结束的时候,i 的值 已经不变了.所以出现了以上问题.

查询了一些结论,最终如下结论:

python里, 非局部变量绑定的是空间, 而不是值本身,所以,生成的函数i, 相对于函数f 来说, 是全局变量, 所以绑定的是 i 所在的内存地址.

所以导致了,生成的四个函数所得值时相同的.

那么如何实现呢? 将 i 变成局部变量, 变成i 的一个参数, 并赋予一个默认值,这样, 函数f绑定的就是值, 而不是内存地址:

def multipliers(n):

  funcs = []

  for i in range(n):

    def f(x, m=i):  #每次生成函数, i的值, 都被绑定到函数本身

      return x * m

    funcs.append(f)

  return funcs

g0, g1, g2, g3 = mutipliters(4)

print(g0(10))                 # 0

print(g1(10))                 # 10

print(g1(10))                 # 20

print(g1(10))                 # 30

有兴趣的可以查询一下  python 延迟绑定和闭包的问题~

ps: 为什么将 x 换成 *arg, 出现如下情况???

def multipliers(n):

  funcs = []

  for i in range(n):

    def f(*arg):  #每次生成函数, i的值, 都被绑定到函数本身

      return arg * i

    funcs.append(f)

  return funcs

g0, g1, g2, g3 = mutipliters(4)

print(g0(10))          #  (10, 10, 10)

目前不明白~欢迎赐教