首页 > 解决方案 > list.clear() 与 list = [] 有何不同?

问题描述

函数的预期目标foo是将作为参数提供的数字添加到列表中,如果为 0,则重置列表。首先我写了这个程序:

def foo(n, bar = []):
    if n == 0:
        bar = []
        print("list empty")
    else:
        bar.append(n)
        for y in bar:
            print(y, end=', ')
        print()

foo(5)
foo(3)
foo(0)
foo(6)

输出:

5, 
5, 3, 
list empty
5, 3, 6, 

但它看起来bar = []被忽略了。然后我改变bar = []bar.clear()它,它按我的想法工作:

def foo(n, bar = []):
    if n == 0:
        bar.clear()
        print("list empty")
    else:
        bar.append(n)
        for y in bar:
            print(y, end=', ')
        print()

foo(5)
foo(3)
foo(0)
foo(6)

输出:

5, 
5, 3, 
list empty
6,

我不明白为什么bar.clear()工作方式与bar = []因为clear()应该不同

从集合中删除所有元素。

所以同样的事情bar = []

编辑:我不认为我的问题与“Least Astonishment”和 Mutable Default Argument重复,我知道

默认值仅评估一次。

(来自官方教程)但我要问的是,为什么bar = []不编辑(在这种情况下清除)列表,而追加和清除呢?

标签: pythonpython-3.x

解决方案


bar = [] 重新绑定 bar;它创建一个全新的 empty list,并将名称绑定bar到它。以前是什么并不重要bar;它本来可以是 a int、 atupledict,现在已经无关紧要了,因为它现在绑定到一个全新的list。旧的绑定不再存在于当前的方法调用中,但原来的绑定list 作为默认参数的值仍然存在foo(注意:由于这种混淆,可变默认值被认为是令人惊讶和丑陋的)。

bar.clear()在现有 的 上调用一个方法list,它告诉它list清除自己(并且对bar所指的内容没有影响;最好是带有方法的东西clear,但除此之外,它并不真正要求它是 a list)。由于它 bar您开始时相同(引用缓存在函数默认值中的相同可变默认值),这会影响您未来的调用(因为bar继续将list您提供的可变默认值引用)。


推荐阅读