class list_class:
def __init__(self, list_=[]):
self.list_ = list_
def add_item(self, item):
self.list_ += [item]
>>> x = list_class()
>>> y = list_class()
>>> x.list_
[]
>>> y.list_
[]
>>> x.add_item(1)
>>> x.list_
[1]
>>> y.list_
[1]
Why does calling add_item() on x change the list_ variable on both instances?
Using list_=[]
in a method argument is a bad Python idiom, for the reason you've discovered. Use the following instead:
class ListClass:
def __init__(self, list_=None):
if list_ is None:
list_ = []
self.list_ = list_
def add_item(self, item):
self.list_.append(item)
list_
is set to []
when __init__
is initially parsed. A list, however, is mutable, and not copied upon assignment. So when the __init__
method is run, each time, it uses the same initial list. With the above replacement, list_
is assigned to a new list every time __init__
is run, and the problem is circumvented. The same holds for a dict as a default for function argument value. It doesn't matter if the list or dict are empty or contain values (__init__(self, list_=[5])
would have had the same problem: don't use a mutable variable in a function argument as a default value.
See the warning in the tutorial section of default function arguments.
Other more Pythonic idioms are using CamelCase for class names, and using somelist.append(item)
instead of somelist += [item]
.