Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Scope of function parameter python

I have this code snippet

def fun(i = []):
    print("i is", i)
    i.append(1)
    
for k in range(5):
    print("k is", k)
    fun()

And its output

k is 0
i is []
k is 1
i is [1]
k is 2
i is [1, 1]
k is 3
i is [1, 1, 1]
k is 4
i is [1, 1, 1, 1]

My understanding till today was, For every function call the parameter will use its default value if no explicit value provided. But here even after not providing any value for i while calling fun from the loop you can see i is getting updated with respect to the previous function call.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I was expecting something like this as the answer:

k is 0
i is []
k is 1
i is []
k is 2
i is []
k is 3
i is []
k is 4
i is []

Don’t we have scope of a function parameter within that function call ?

>Solution :

Beware of default mutable arguments!

The default mutable arguments of functions in Python aren’t really initialized every time you call the function. Instead, the recently mutated values are used as the default value.

The first time that the function is called, Python creates a persistent object for the mutable container. Every subsequent time the function is called, Python uses that same persistent object that was created from the first call to the function.

def some_func(default_arg=[]):
    default_arg.append("some_string")
    return default_arg
Output:

>>> some_func()
['some_string']
>>> some_func()
['some_string', 'some_string']
>>> some_func([])
['some_string']
>>> some_func()
['some_string', 'some_string', 'some_string']

When we explicitly passed [] to some_func as the argument, the default value of the default_arg variable was not used, so the function returned as expected.

Output:

>>> some_func.__defaults__ #This will show the default argument values for the function
([],)
>>> some_func()
>>> some_func.__defaults__
(['some_string'],)
>>> some_func()
>>> some_func.__defaults__
(['some_string', 'some_string'],)
>>> some_func([])
>>> some_func.__defaults__
(['some_string', 'some_string'],)

A common practice to avoid bugs due to mutable arguments is to assign None as the default value and later check if any value is passed to the function corresponding to that argument. Example:

def some_func(default_arg=None):
    if default_arg is None:
        default_arg = []
    default_arg.append("some_string")
    return default_arg

Source: wtfpython

Thanks to TomKerzas for providing another excellent resource for information on this topic here

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading