Common Python Beginner Mistakes With Default Arguments

When I first began using Python and object-oriented programming (OOP) methods in college, a friend asked for my stack and I responded that I knew Python well. He requested access to my GitHub repository, and after a while, he pointed out some code I had written recently and requested that I run it several times, which I did. The error was caused by passing a mutable object as an argument. I only realized this after the third trial when I noticed a weird behavior in my Python code.

When using OOP in Python, we deal with classes and objects, as well as numerous arguments and parameters. Most people may not be aware of the fundamental concept behind using mutable objects as default parameters when working with OOP in Python.

In this tutorial, I'll provide a thorough explanation of the terms used to describe different types of object arguments in Python, as well as best practices for using default object arguments.

1_IRGB-4OAoO8KSqH_huDPFw.png

Prerequisite

To make the most of this tutorial, you should be familiar with the following concepts:

  1. Object-oriented programming in Python
  2. A working code editor or IDE. I make use of VSCode for the purpose of this tutorial.

An Overview Of Mutability In Python

Objects in Python include lists, dictionaries, and functions. Everything in Python is treated as an object with its own unique properties and methods.

mutable.png

In Python OOP, mutable objects are those whose values can change. Anything whose state can change is referred to as mutable. Examples are lists, dictionaries, and sets.

Immutable objects includes numbers, strings, and tuples. These objects do not change their internal state values or properties.

Arguments are specified after the function name and contain information about the function.

There are three main types of arguments in Python.

  • Default arguments
  • Keyword arguments
  • Arbitrary arguments

But for the sake of simplicity, we will only look into default arguments.

The wired behavior behind mutable object arguments

In Python, an empty argument is made with an = sign assigned to a variable.

def print_reversed(my_list =[]):
if my_list:
  pass
else:
    my_list.append("Do use mutable objects")
    output = ['do not'] + my_list
    return output

Above is a function to print the reversed data of any value passed into my_list. Here my_list is a default argument that takes in an empty list. If you try running this code multiple times, you will get different patterns of results!

Recall the definition we discussed above, as mutable means that a value of mutable objects can change its internal state.

Python tries to retain the default value every time the code runs and reassigns the default argument every time the code runs and since its being mutated inside the function, we end up using a different default object value when the function is being called.

The Solution

To solve this problem, use the None keyword as default instead, then the code will look like this;

def print_reversed(my_list = None):
  if my_list:
    pass
  else:
    my_list = []
    my_list.append("Do use mutable objects")
    output = ['do not'] + my_list
    return output

The word None" is used to indicate a null value or absolutely no value. None is distinct from 0 (zero), False (zero), and an empty string. None" is a distinct data type (NoneType), and only None" is capable of being None".

These are quite common mistakes most novices in python make, I always find myself going over my codes and making lots of adjustments to optimizing mutable default arguments.

Conclusion

We have come to the end of this tutorial; I hope you were able to learn the little hack to employ when working with OOP in Python, as well as to understand mutable objects and arguments.