Precautions when giving default values to arguments in Python function definitions

Python allows arguments to have default values when defining a function.

The function below retrieves a value by specifying a key to the dictionary, but returns the default value 0 if the dictionary does not contain a key.

Python


def get(dic, key, default = 0):
    if key in dic:
        return dic[key]
    else:
        return default

let's do it.

Python


#Prepare a dictionary
times_in_PPAP = {"pen": 2, "pineapple": 1, "apple": 1}

print "pen:\t",    get(times_in_PPAP, "pen")
print "apple:\t",  get(times_in_PPAP, "apple")
print "banana:\t", get(times_in_PPAP, "banana")

result


pen:	2
apple:	1
banana:	0

Since pen and apple are in the dictionary, their values are returned. Since banana is not included in the dictionary, the default value of 0 is returned.

There is no problem so far. Now consider the following case.

Python


dict_PPAP = {"PP": ["pen", "pineapple"], "AP": ["apple", "pen"],
             "PPAP": ["pen", "pineapple", "apple", "pen"]}

This dictionary is a dictionary that stores an array of the corresponding prototypes for the acronym. Let's write a function similar to the above for this dictionary.

Python


def restore_acronym(dic, key, default = []):
    if key in dic:
        return dic[key]
    else:
        return default

I will try it.

Python


print "PP:", restore_acronym(dict_PPAP, "PP")
print "AP:", restore_acronym(dict_PPAP, "AP")
print "PA:", restore_acronym(dict_PPAP, "PA")

result


PP: ['pen', 'pineapple']
AP: ['apple', 'pen']
PA: []

The PP and AP are included in the dictionary, so the original array is returned. For PA, the default empty array is returned because it is not included in the dictionary. I got the results I wanted.

However, using a function written this way can have surprising results. Let's get the default empty array from this function and add some elements as follows:

Python


my_list = restore_acronym(dict_PPAP, "PA")
print my_list

my_list.append("pico")
my_list.append("taro")
print my_list

result


[]
['pico', 'taro']

This operation seems to be fine, but it has surprising consequences. After this operation, try to get the default value by specifying a key that is not included in the dictionary (for example, BANANA).

Python


print "BANANA:", restore_acronym(dict_PPAP, "BANANA")

result


BANANA: ['pico', 'taro']

You can see that the effect of the previous operation remains in the default value.

This is because the default arguments for Python functions are evaluated only once when the module is loaded.

For example, consider the following function.

Python


from datetime import datetime

def my_log(message, timestamp = datetime.now()):
    print "{timestamp}: {message}".format(timestamp = timestamp, message = message)

This function is intended to output the time stamp at that time when outputting the log message. However, when I actually run it, it looks like this:

Python


from time import sleep

my_log("0 sec")
sleep(1)
my_log("1 sec")

result


2016-12-31 23:59:59: 0 sec
2016-12-31 23:59:59: 1 sec

The same time stamp is displayed even though 1 second has passed. As mentioned above, the default arguments are evaluated only once when the function loads. Therefore, the default argument stores the time stamp when the function is loaded, and the time stamp does not change each time the function is called.

To get this function to work as intended, use None and modify it as follows:

Python


def my_log2(message, timestamp = None):
    if timestamp is None:
        timestamp = datetime.now()
    print "{timestamp}: {message}".format(timestamp = timestamp, message = message)

my_log2("0 sec")
sleep(1)
my_log2("1 sec")

result


2016-12-31 23:59:59: 0 sec
2017-01-01 00:00:00: 1 sec

By specifying None as the default argument and bringingtimestamp = datetime.now ()inside the function, the timestamp is obtained for each function call.

This solved the timestamp problem.

Now let's get back to the PPAP issue. In this case, since an empty array was specified as the default argument, one empty array object was created when the function was loaded, and that object was reused, so the problem was that changes to that empty array were saved. This can also be resolved by specifying None as the default argument.

Python


def restore_acronym2(dic, key, default = None):
    if default is None:
        default = []
    if key in dic:
        return dic[key]
    else:
        return default

Now every time you call a function, an empty array of objects will be created. In fact, getting the default empty array and adding elements to it has no effect on the next default call.

Python


my_list2 = restore_acronym2(dict_PPAP, "PA")
print my_list2

my_list2.append("pico")
my_list2.append("taro")
print my_list2

print "BANANA:", restore_acronym2(dict_PPAP, "BANANA")

result


[]
['pico', 'taro']
BANANA: []

Note that in Python, setting a mutable object as the default argument of a function can cause unexpected bugs.

Enjoy!

Recommended Posts

Precautions when giving default values to arguments in Python function definitions
Precautions when pickling a function in python
Things to watch out for when using default arguments in Python
Automatically register function arguments to argparse in Python
[Python] Precautions when assigning values to multidimensional arrays
Precautions when using pit in Python
Included notation in Python function arguments
Precautions when passing def to sorted and groupby functions in Python? ??
To set default encoding to utf-8 in python
How to receive command line arguments in Python
To execute a Python enumerate function in JavaScript
Precautions when dealing with control structures in Python 2.6
Error when trying to install psycopg2 in Python
[Python] I want to know the variables in the function when an error occurs!
How to take multiple arguments when doing parallel processing using multiprocessing in python
About function arguments (python)
Things to keep in mind when developing crawlers in Python
Get environment variables in Python, otherwise set default values
Precautions when dealing with ROS MultiArray types in Python
Things to keep in mind when copying Python lists
Tips and precautions when porting MATLAB programs to Python
Set constructor keyworded arguments to mock attributes in Python
Things to note when initializing a list in Python
Python: About function arguments
Swapping values in Python
Specifies the function to execute when the python program ends
How to exit when using Python in Terminal (Mac)
Execute Python function from Powershell (how to pass arguments)
Things to keep in mind when processing strings in Python2
[Python] How to output the list values in order
When will the default arguments be bound in python? When variables are bound in closure lazy evaluation.
Things to keep in mind when processing strings in Python3
I want to do something in Python when I finish
To receive multiple return values ​​from a function executed using parallel processing (Pool) in Python
[Small story] A painstaking measure when you have to execute a function before import in Python
How to sample from any probability density function in Python
To return char * in a callback function using ctypes in Python
Convenient writing method when appending to list continuously in Python
How to specify command line arguments when debugging in PyCharm
What to do when "SSL: CERTIFICATE_VERIFY_FAILED _ssl.c: 1056" appears in Python
I tried to implement the mail sending function in Python
[Introduction to Udemy Python3 + Application] 50. Positional arguments, keyword arguments, and default arguments
Things to keep in mind when using Python with AtCoder
Precautions when changing unix time to datetime type in pandas
Things to keep in mind when using cgi with python.
[Introduction to Udemy Python3 + Application] 51. Be careful with default arguments
Covector to think in function
Create a function in Python
To flush stdout in Python
Use callback function in Python
ntile (decile) function in python
Login to website in Python
Receive runtime arguments in Python 2.7
Attention when os.mkdir in Python
Draw implicit function in python
Speech to speech in python [text to speech]
Immediate function in python (lie)
How to develop in Python
Transfer parameter values in Python
Post to Slack in Python
How to not escape Japanese when dealing with json in python