Search code examples
pythonapi-designin-placemutability

Change object directly in function is anti-pattern in python?


Assume that we have to get some value and change it from function.

Way-1

def change_b(obj):
    obj['b'] = 4


result = {'a': 1, 'b': 2}
change_b(obj=result)
print(result)

As you know that function change_b() change result['b']'s value directly in function.

Way-2

from copy import deepcopy


def change_b(obj):
    temp = deepcopy(obj)
    temp['b'] = 4
    return temp


result = {'a': 1, 'b': 2}
result = change_b(obj=result)
print(result)

But Way-2 copying object to new object and replace value from new object.

So, original object doesn't affect anything. (Also, no side-effect)

Maybe Way-2 is more safe, because it doesn't change original object.

I wonder that which one is more general and pythonic way?

Thanks.


Solution

  • Summary

    If the API is explicit that it is updating its input, Way-1 is fine and desirable: add_route(route_map, new_route).

    If the API is primarily about doing something else, then Way-2 avoids unintended side-effects.

    Examples within Python

    Way-1: The dict.update() and list.sort() do in-place updates because that is their primary job.

    Way-2: The builtin sorted() function produces a new sorted list from its inputs which it takes care not to alter. Roughly, it does this:

    def sorted(iterable, *, key=None, reverse=False):
        result = list(iterable)                # copy the data
        result.sort(key=key, reverse=reverse)  # in-place sort
        return result
    

    Hope that clarifies when to copy and when to mutate in-place :-)