Common Python Problems - [2] Mutable Arguments

By JoeVu, at: 14:20 Ngày 11 tháng 1 năm 2023

Thời gian đọc ước tính: 5 min read

None
None

Python Mutable Arguments are a type of argument that can be changed within the function call. These arguments are passed by reference and can be modified within the function. This can cause unexpected side-effects in code, leading to potential errors and unexpected behavior.

Mutable Function Arguments

Python Mutable Arguments are a common issue when programming in Python, as they can cause confusion when trying to debug code. 

For example, if a function takes a list as an argument, changing that list within the function will also change it outside the function. This can be difficult to spot in debugging if you are not expecting the value to change.


def append_to_list(a_list:list, element:int):
    if element > 0:
        a_list.append(element)
    print ("Values inside the function: ", a_list)

a_list = [1, 2, 3]
append_to_list(a_list, 5)
print ("Values outside the function: ", a_list)

Output

Values inside the function:  [1, 2, 3, 5]
Values outside the function:  [1, 2, 3, 5]

As the function append_to_list() modified the original list by adding the element to it if the element is greater than 0. This behavior is not always desirable, as it can lead to an unexpected result and difficult-to-trace bugs.

A common way to avoid these issues is to make a copy of the argument before modifying it. For example, the following code will not modify the original list:

def append_to_list(a_list:list, element:int):
    if element > 0:
        a_list = a_list + [element]
    print ("Values inside the function: ", a_list)

a_list = [1, 2, 3]
append_to_list(a_list, 5)
print ("Values outside the function: ", a_list)

Output 

Values inside the function:  [1, 2, 3, 5]
Values outside the function:  [1, 2, 3]

The same issue happens with dictionary and set.

def update_dictionary(a_dict, keyword, value):
    a_dict[keyword] = value
    print ("Values inside the function: ", a_dict)

a_dict = {"count": 1}
update_dictionary(a_dict, "message", "good")
print ("Values outside the function: ", a_dict)

Output 

Values inside the function:  {'count': 1, 'message': 'good'}
Values outside the function:  {'count': 1, 'message': 'good'}


Solutions

1. Create a copy of the mutable argument before modifying it

Example:

import copy

def update_list(a_list):
    a_list_copy = copy.copy(a_list)
    a_list_copy.append(4)
    return a_list_copy

original_list = [1, 2, 3]
modified_list = update_list(original_list)
print(original_list)
print(modified_list)

Output 

[1, 2, 3]
[1, 2, 3, 4]

2. Use immutable arguments instead of mutable arguments. Ex: use a library like Frozen Dict to create an immutable dictionary


from frozendict import frozendict
frozen_dict = frozendict({ 'hello': 'World' })
print(frozen_dict)
frozendict.frozendict({'hello': 'World'})

 

<frozendict>print(frozen_dict['hello'])</frozendict>
<frozendict>World</frozendict>

 

frozen_dict["another_key"] = "value"

it raises an exception with TypeError


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[44], line 1
----> 1 frozen_dict["another_key"] = "value"
File ~/.pyenv/versions/3.10.8/envs/glinteco-website/lib/python3.10/site-packages/frozendict/core.py:198, in frozendict.__setitem__(self, key, val, *args, **kwargs)
    197 def __setitem__(self, key, val, *args, **kwargs):
--> 198     raise TypeError(
    199         f"'{self.__class__.__name__}' object doesn't support item "
    200         "assignment"
    201     )
TypeError: 'frozendict' object doesn't support item assignment

It is important to be aware of Python Mutable Arguments and how they can affect the behavior of your code. To avoid unexpected side-effects, it is best to use immutable arguments instead. Immutable arguments cannot be changed within the function and are passed by value instead of by reference.

This can help make debugging easier and reduce the chances of unexpected behavior.


Theo dõi

Theo dõi bản tin của chúng tôi và không bao giờ bỏ lỡ những tin tức mới nhất.