Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Comments on Understanding mutable default arguments in Python

Parent

Understanding mutable default arguments in Python

+9
−0

Consider this code example:

def example(param=[]):
    param.append('value')
    print(param)

When example is repeatedly called with an existing list, it repeatedly appends to the list, as one might expect:

>>> my_list = []
>>> example(my_list)
['value']
>>> example(my_list)
['value', 'value']
>>> example(my_list)
['value', 'value', 'value']
>>> my_list
['value', 'value', 'value']
If it's called with an empty list each time, it seems that each empty list is considered separately, which also makes sense:
>>> example([])
['value']
>>> example([])
['value']
>>> example([])
['value']
However, if called without passing an argument - using the default - it seems to "accumulate" the appended values as if the same list were being reused:
>>> example()
['value']
>>> example()
['value', 'value']
>>> example()
['value', 'value', 'value']

Some IDEs will warn that param is a "mutable default argument" and suggest changes.

Exactly what does "mutable default argument" mean, and what are the consequences of defining param this way? How is this functionality implemented, and what is the design decision behind it? Is it ever useful? How can I avoid bugs caused this way - in particular, how can I make the function work with a new list each time?

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.
Why should this post be closed?

2 comment threads

TODO (1 comment)
Split question (1 comment)
Post
+1
−1

Everything you put on the line with def is global (global to the file, not as in the global keyword), so the (initially empty) list you create with param=[] persists and gets reused between calls to example(). You probably want to create a local list for each invocation instead. For that, you have to find a way to put param = [] inside the method.

The normal way is:

def example(param: list | None = None):
    if param is None:
        param = []

Python is powerful and fun, so you can come up with more pithy ways of doing it. However, you will then have to add comments for other people who don't expect it, and IDEs which don't understand them, so they will not be so pithy in the end. You're best off just using the normal way above.

I think other details are best addressed in separate questions, such as:

  • Mutable vs. immutable in Python
  • Implementation details of the interpreter
  • The history of Python design decisions
  • Why not just def (param=None):
  • Why not just if param:

Please comment on this question if you do ask these separately, and want me to answer them.

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.

1 comment thread

I appreciate the feedback, and agree that certain topics can be split off - I'll think about it more ... (2 comments)
I appreciate the feedback, and agree that certain topics can be split off - I'll think about it more ...
Karl Knechtel‭ wrote about 1 year ago · edited about 1 year ago

I appreciate the feedback, and agree that certain topics can be split off - I'll think about it in more detail. I don't require answers for them; while you're of course always welcome in the Codidact model to add your own answers, the point here is very explicitly for me to share knowledge that I already have, and to establish canonicals that others can be pointed at - on topics whose value has already been proven by extensive Stack Overflow experience.

I'm not really trying to get into implementation details more than the minimum; but it is necessary to have a proper understanding in order to reason about the code properly. There is one core issue here: why code behaves in a specific way when using mutable default arguments, and what to do about it.

In any case, the "global to the file" mental model here doesn't really work. I can't really glean anything from it, and anyway global variables created with global also are on a per-file basis.

matthewsnyder‭ wrote about 1 year ago

Fair enough. I know that this is one of your self-answer canonicals. I think the question is interesting, but I noticed all the answer you posted are quite long. So I decided to post a shorter one for people who are in a hurry, and also as an example for how it can be made more succinct. I operate under the assumption that it is ideal for answers to not be longer than 3-5 paragraphs, since the UX makes long answers hard to read and they seem less common.

For the global, my point was that it behaves much like if you defined a default_list = [] at the top level scope of the file and referred to it as the default value from inside your method. I do think it's a reasonably accurate and simple model, but obviously neither of us here is actually confused about this, so perhaps we will one day hear from an actual newbie...