+ 5
A strange behavior
def f(q, my_list = []): my_list = my_list + q return my_list a =[1] print(f(a)) a = [2] print(f(a)) Output : [1] [2] But, def f(q, my_list = []): my_list += q return my_list a =[1] print(f(a)) a = [2] print(f(a)) Output: [1] [1, 2] I thought the answer will be the second one on both occasion (cz lists are mutable(?)). But I found these two separate ones. Why did that happen? And are these two, my_list = my_list + q and my_list += q different from each other? I thought they are same and do the same work.
3 Answers
+ 7
In short, the expression, 'list1 = list1 + a' changes the list's reference.
Thanks đđąđąđđš đđĄđđČđđ„. It really helped.
+ 4
Every function has an attribute __defaults__.
The objects in there are what will be assigned to the default parameter whenever you call the function and nothing is passed.
These default objects are created and stored only once when the function is defined.
So when you fill up a default list from the function, it will still contain that stuff the next time you call it. Because it's still the very same list.
When across several calls you do pass something, then the parameter will be reassigned to whatever you passed. But the default object is still there - it still sits in that attribute.
So when you call the function without argument next time, you will pick up right where you left and continue filling it.
Try this for illustration:
def f(n=[]):
print(f.__defaults__)
n += [1]
f()
f()
f([7])
f()
f()
+ 3
The '+' operator forces to instanciate a new object, while the '+=' operator changes the current object... or not : it depends whether the object is immutable or not.
When working with lists (and sets), which are mutable collections, always use their built-in methods (here '.extend'), so that it shows clearly that you are modifying the object, and not creating a new one.
Indeed, with '+=', we could think that it creates a new list. So use '.extend' here.