Shouldn't lst point to [2], since after lst.append(x) lst not point to None anymore? Why the next execution still make lst point to none?

That is exactly what you prevent by using the lst=None, lst = [] if lst is None else lst construction. While the default arguments for the function are evaluated only once at compile time, the code within the function is evaluated each time the function is executed. So each time you execute the function without passing a value for lst, it will start with the default value of None and then immediately be replaced by a new empty list when the first line of the function is executed.

If you instead were to define the function like this:

def append_if_even(x, lst=[]):
    if x % 2 ==0:
        lst.append(x)
    return lst

Then it would act as you describe. The default value for lst will be the same list (initially empty) for every run of the function, and each even number passed to the function will be added to one growing list.

For more information, see "Least Astonishment" and the Mutable Default Argument.

Answer from glibdud on Stack Overflow
🌐
Reddit
reddit.com › r/python › today i re-learned: python function default arguments are retained between executions
r/Python on Reddit: Today I re-learned: Python function default arguments are retained between executions
January 20, 2023 - No. strings are immutables in python. It's perfectly safe to write ... “stick to literals” is not good advice. List and dictionary literals would be problematic as default parameter values since those are mutable types. Ironically the example you’ve given here could be simplified by just using the string literal as the default since strings are immutable.
Discussions

Why no .get(idx[, default]) on python list??
There was a lengthy thread on this on Python-Ideas a couple of years ago: https://mail.python.org/archives/list/python-ideas@python.org/thread/LLK3EQ3QWNDB54SEBKJ4XEV4LXP5HVJS/ The clearest explanation of the most common objection was from Marc-Andre Lemburg: dict.get() was added since the lookup is expensive and you want to avoid having to do this twice in the common case where the element does exist. It was not added as a way to hide away an exception, but instead to bypass having to generate this exception in the first place. dict.setdefault() has a similar motivation. list.get() merely safes you a line of code (or perhaps a few more depending on how you format things), hiding away an exception in case the requested index does not exist. If that's all you want, you're better off writing a helper which hides the exception for you. I argue that making it explicit that you're expecting two (or more) different list lengths in your code results in more intuitive and maintainable code, rather than catching IndexErrors (regardless of whether you hide them in a method, a helper, or handle them directly). So this is more than just style, it's about clarity of intent. More on reddit.com
🌐 r/Python
94
144
June 23, 2022
list - Getting a default value on index out of range in Python - Stack Overflow
a = ['123', '2', 4] b = a[4] or 'sss' print b I want to get a default value when the list index is out of range (here: 'sss'). How can I do this? More on stackoverflow.com
🌐 stackoverflow.com
Initialise a list to a specific length in Python - Stack Overflow
How do I initialise a list with 10 times a default value in Python? I'm searching for a good-looking way to initialize a empty list with a specific range. So make a list that contains 10 zeros or More on stackoverflow.com
🌐 stackoverflow.com
Why isn't mutable default value (`field = List[int] = []`) a documented feature?
Hi! I was surprised a List[...] can get an empty list as a default value correctly - every instance will gets its own copy (dataclasses requires to use a default_factory). class ShoppingCart(pydant... More on github.com
🌐 github.com
1
38
🌐
LabEx
labex.io › tutorials › python-how-to-initialize-lists-with-default-values-420188
How to initialize lists with default values | LabEx
## Initialize a list with a specific default value default_zeros = [0] * 5 ## Creates [0, 0, 0, 0, 0] default_strings = [''] * 3 ## Creates ['', '', ''] ## Creating a list to track student scores num_students = 5 student_scores = [0] * num_students ## Initializing a 2D list matrix = [[0 for _ in range(3)] for _ in range(3)] Choose the initialization method that best fits your specific use case ... When learning list initialization, practice is key. LabEx provides interactive Python environments to experiment with these techniques.
🌐
HackerOne
hackerone.com › blog › python-pitfalls-perils-using-lists-and-dicts-default-arguments
Python Pitfalls: The Perils of Using Lists and Dicts as Default Arguments | HackerOne
December 19, 2023 - In summary, while Python's default argument feature is handy, it requires careful consideration when dealing with mutable types. Remember: Use Immutable Defaults: Stick to immutable types like integers, strings, or None for default arguments. Create New Instances Inside: For lists or dictionaries, initialize them within the function body if the argument is None.
🌐
GeeksforGeeks
geeksforgeeks.org › python › use-mutable-default-value-as-an-argument-in-python
Use mutable default value as an argument in Python - GeeksforGeeks
July 23, 2025 - # Python mutable value (List) demo_list = [1, 2, 3, 4, 5] print("Original List:", demo_list) demo_list[0] = 10 print("Modified List:", demo_list) ... Contrary to mutable values in Python, there is an immutable value that cannot be edited or modified as shown below: ... # Python immutable values (Tuple) demo_tuple = (1, 2, 3, 4, 5) print("Original Tuple", demo_tuple) demo_tuple[0] = 10 print("Modified Tuple", demo_tuple) ... Now that we know what a mutable value is in Python and when we use such mutable values as default values for parameters when defining a function in Python it is called a mutable default value.
🌐
Hucci Blog
huccihuang.github.io › posts › Why-shouldn't-we-use-a-list-as-the-default-parameter-of-a-function
Python Common Mistakes: Why shouldn't we use a list as the default parameter of a function | Hucci Blog
May 6, 2024 - This is because default parameters are attributes of the function, and they are defined when the function is defined, not when the function is called.
🌐
Plain English
python.plainenglish.io › the-curious-case-of-pythons-default-list-argument-d07438af6bfd
The Curious Case of Python’s Default List Argument | Python in Plain English
January 6, 2025 - Default parameters in Python allow you to assign default values to function arguments, making them optional during a function call. While this feature is incredibly useful, it can lead to unexpected behaviour when dealing with mutable types like lists.
🌐
Reddit
reddit.com › r/python › why no .get(idx[, default]) on python list??
r/Python on Reddit: Why no .get(idx[, default]) on python list??
June 23, 2022 -

Hi all,

today it happened once again that I could really use a .get(idx[, default]) method on python lists. Here is a brief example why it could be useful (I know there are many alternative solutions to this specific problem here, so please focus generally on the idea of .get for lists).

file_name = 'test.png'
if '.' in file_name:
    extension = file_name.rsplit('.', maxsplit=1)[1]
else:
    extension = ''

If we had such a method we could make the code much more concise

file_name = 'test.png'
extension = file_name.rsplit('.', maxsplit=1).get(1, '')

I wonder why this useful method does not exist, especially since it is available for dicts.

dd = {'a': 'AAA'}
print(f"{dd['a']}; {dd.get('a')}; {dd.get('c')}; {dd.get('c', 'nothing here')}; ")
# AAA; AAA; None; nothing here;

Thoughts / ideas why this is not present? Are there valid reasons not to have this method? Is it not available because someone has to invest the work to code it? How could something like this be initiated? :)

Top answer
1 of 23
155
There was a lengthy thread on this on Python-Ideas a couple of years ago: https://mail.python.org/archives/list/python-ideas@python.org/thread/LLK3EQ3QWNDB54SEBKJ4XEV4LXP5HVJS/ The clearest explanation of the most common objection was from Marc-Andre Lemburg: dict.get() was added since the lookup is expensive and you want to avoid having to do this twice in the common case where the element does exist. It was not added as a way to hide away an exception, but instead to bypass having to generate this exception in the first place. dict.setdefault() has a similar motivation. list.get() merely safes you a line of code (or perhaps a few more depending on how you format things), hiding away an exception in case the requested index does not exist. If that's all you want, you're better off writing a helper which hides the exception for you. I argue that making it explicit that you're expecting two (or more) different list lengths in your code results in more intuitive and maintainable code, rather than catching IndexErrors (regardless of whether you hide them in a method, a helper, or handle them directly). So this is more than just style, it's about clarity of intent.
2 of 23
25
In any case it would have ever been helpful for me, there's a better way to do what I was trying to do. In your case you can use os module which I'd argue is a bit more idiomatic. os.path.splitext(file_name)[1].lstrip('.') Or since if I have file paths I ususally like to work with pathlib: Path(file_name).suffix.lstrip('.') Either case makes it very clear what is happening
Find elsewhere
🌐
Quantifiedcode
docs.quantifiedcode.com › python-anti-patterns › correctness › mutable_default_value_as_argument.html
Using a mutable default value as an argument — Python Anti-Patterns documentation
Passing mutable lists or dictionaries as default arguments to a function can have unforeseen consequences. Usually when a programmer uses a list or dictionary as the default argument to a function, the programmer wants the program to create a new list or dictionary every time that the function is called. However, this is not what Python does.
🌐
Nikos7am
nikos7am.com › posts › mutable-default-arguments
My Python Blog | Avoid using an empty list as a default argument to a function
June 4, 2018 - This is not the behavior we wanted! A new list is created once when the function is defined, and the same list is used in each successive call. Python’s default arguments are evaluated once when the function is defined, not each time the function is called.
🌐
Note.nkmk.me
note.nkmk.me › home › python
Default Parameter Values in Python Functions | note.nkmk.me
May 12, 2025 - def func_default_list(l=[0, 1, ... # {'default': 0, 'new': 100, 'new2': 200} ... To avoid this behavior, you can use None as the default value and create a new object inside the function....
🌐
blog
blog.wxm.be › 2012 › 09 › 08 › initialise-python-list-to-length-with.html
Initialise Python List to a Length with Default Values | blog
September 8, 2012 - To create a list in python 3 and fill it with default values, you can simply issue
🌐
Chelsea Troy
chelseatroy.com › 2022 › 03 › 25 › pythons-sneaky-default-argument-behavior-and-what-to-do-about-it
Python’s Sneaky Default Argument Behavior and What to Do About It
February 7, 2023 - Python evaluates default arguments when it places the definition of the function into the environment. Not when it runs that function. So the default arguments keep the id they had at function definition time. No problem when your defaults are immutable. But a list is mutable.
🌐
Cwestblog
cwestblog.com › 2015 › 02 › 13 › python-snippet-get-list-item-or-get-default
Python Snippet – Get List Item or Get Default – Chris West's Blog
def get_at(list, index, default=None): return list[index] if max(~index, index) < len(list) else default [/code] The above function can be used in order to either return the value at the specified index or a default value if the index doesn't exist: [code language=python] lists = [[], ['Hello world!!!'], range(10)[3:]] for list in lists: print 'list = {}'.format(list) print '- first value: {}'.format(get_at(list, 0)) print '- second value: {}'.format(get_at(list, 1)) print '- last value: {}'.format(get_at(list, -1)) print '- 5th value (defaults to "missing"): {}'.format(get_at(list, 4, 'missing')) print '' [/code] The above code outputs the following: [code language=plain] list = [] - first value: None - second value: None - last value: None - 5th value (defaults to "missing"): missing list = ['Hello world!!!'] - first value: Hello world!!!
🌐
The Hitchhiker's Guide to Python
docs.python-guide.org › writing › gotchas
Common Gotchas — The Hitchhiker's Guide to Python
A new list is created once when the function is defined, and the same list is used in each successive call. Python’s default arguments are evaluated once when the function is defined, not each time the function is called (like it is in say, Ruby).
🌐
GeeksforGeeks
geeksforgeeks.org › default-arguments-in-python
Default arguments in Python - GeeksforGeeks
If the function is called without the argument, the argument gets its default value. Python has a different way of representing syntax and default values for function arguments. Default values indicate that the function argument will take that value if no argument value is passed during the function call.
Published: September 11, 2024
🌐
GeeksforGeeks
geeksforgeeks.org › python › defaultdict-in-python
Defaultdict in Python - GeeksforGeeks
If the key does not exist: default_factory is called to generate a default value. ... This mechanism avoids errors and makes code simpler when handling missing keys. When the list class is passed as the default_factory argument, a defaultdict ...
Published: May 19, 2026