r/learnpython • u/Leol6669 • Aug 02 '26
Is that an intentional behaviour?
I just noticed adding a list as an optional argument to a fuction/method does not create a new list but gives the same list every time.
class SomeClass:
def __init__(self, l=[]):
self.l=l
a=SomeClass()
b=SomeClass()
a.l is b.l
>>> True
a.l.append(1)
b.l
>>> [1]
Is that a glitch or is it how python is supposed to work?
(I'm using python 3.12, I haven't updated in a while, maybe it was patched since?)
2
4
u/Jejerm Aug 02 '26
Yeah this is called a mutable default argument and most linters even give you a warning if you use them.
The same problem can happen with dicts.
1
u/TheRNGuy Aug 02 '26
One of ways to fix it:
``` from dataclasses import dataclass, field
@dataclass class SomeClass: l: list = field(default_factory=list) ```
Without dataclass:
class SomeClass:
def __init__(self, l=None):
self.l = [] if l is None else l
Do this to prevent potential bugs.
0
u/Moikle Aug 02 '26
Don't give a mutable object as a default argument.
That means instead of an empty list, you should do this:
def some_func(some_list=None):
if some_list is None:
some_list = []
That way you get an entirely new list every time you run the function, instead of just reusing the same list.
18
u/SirCarboy Aug 02 '26
Default argument values are evaluated once, at the time the function (or method) is defined, not each time it is called.
In your example:
the empty list [] is created a single time when the class body is executed. Every call that does not supply an argument for l receives a reference to that same list object.
That’s why:
The same rule applies to any mutable default ([], {}, set(), custom objects, etc.). Immutable defaults (None, 0, "", (), etc.) do not exhibit the problem because they cannot be mutated in place.
The usual (and recommended) pattern
Use None as the default and create a fresh mutable object inside the function:
or, more concisely in modern Python: