Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is list.clear() different from list = []?

The intended objective of function foo is to add the number provided as argument to the list and, in case it is 0, reset the list. First I wrote this program:

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)

output:

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

but it looks like bar = [] is ignored. Then I changed bar = [] with bar.clear() and it works as I thought:

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)

output:

5, 
5, 3, 
list empty
6,

I haven't understood why bar.clear() works differntly from bar = [] since clear() should

Remove all elements from the set.

so the same thing bar = [] does.

Edit: I don't think my question is a duplicate of “Least Astonishment” and the Mutable Default Argument, I'm aware that

The default value is evaluated only once.

(from the official tutorial) but what I am asking is, why bar = [] doesn't edit (in this case clear) the list, while append and clear does?

like image 227
untitled Avatar asked Jun 30 '18 17:06

untitled


1 Answers

bar = [] rebinds bar; it creates a brand new empty list, and binds the name bar to it. It doesn't matter what bar was before; it could have been an int, a tuple, or dict, and it's irrelevant now, because it's now bound to a brand new list. The old binding no longer exists in the current method call, but the original list remains in existence as the value of the default argument to foo (note: Mutable defaults are considered surprising and ugly because of this confusion).

bar.clear() calls a method on the existing list, which tells that list to clear itself (and has no effect on what bar refers to; it better be something with a clear method, but other than that, it's not really required that it be a list). Since it's the same bar you started with (referencing the same mutable default value cached in the function defaults), that affects your future calls (because bar continues to refer to the list you provided as the mutable default).

like image 75
ShadowRanger Avatar answered Oct 26 '22 02:10

ShadowRanger