为什么不能用可变对象作为默认参数的值

为什么不能用可变对象作为默认参数的值

看一个例子

def abc(a, b):
    b.append(a)
    print(b)
    return b

if __name__ == '__main__':
    abc(1, [])
    abc(2, [])
    abc(3, [])
结果和预期的一样:
[1]
[2]
[3]
如果传入参数是默认参数呢?
def abc(a, b=[]):
    b.append(a)
    print(b)
    return b

if __name__ == '__main__':
    abc(1)
    abc(2)
    abc(3)
结果如下:
[1]
[1, 2]
[1, 2, 3]

震惊!

BUG解释

  • def是一条可执行语句,Python 解释器执行 def 语句时,就会在内存中就创建了一个函数对象(此时,函数里面的代码逻辑并不会执行,因为还没调用嘛),在全局命名空间,有一个函数名(变量叫 func)会指向该函数对象,记住,至始至终,不管该函数调用多少次,函数对象只有一个,就是function object,不会因为调用多次而出现多个函数对象。

  • 函数对象生成之后,它的属性:名字和默认参数列表都将初始化完成。

      # 函数的名字
      >>> abc.__name__  
      'abc'
    
      # 函数的默认参数列表
      >>> abc.__defaults__  
      ([1, 2, 3],)
    
  • 初始化完成时,属性 default 中的第一个默认参数 b 指向一个空列表.

  • 当函数第一次被调用时,就是第一次执行 abc()时,开始执行函数里面的逻辑代码(此时函数不再需要初始化了),代码逻辑就是往b中添加一个值为1的元素

  • 第二次调用 func(),继续往numbers中添加一个元素

  • 第三次、四次依此类推

那么我们应该如何避免前面那种情况发生呢?

就是不要用可变对象作为参数的`默认值`。
posted @ 2020-12-09 14:25  rm-rf*  阅读(144)  评论(0编辑  收藏  举报