1

Is there a simple/elegant way to pass an object to a function in a way that does not let it be modified from inside that function? As an example, for a passed array, it should not be possible to perform

array[2]=1 

and change the outer version of the array. That was an example, but I am looking for a solution that does not only work for arrays.

I have considered passing a copy, but this feels a little inelegant as it requires constant use of the copy library, and requires the constant computational effort of copying the object(s).

It is not an option to make the object somehow unmodifiable as a whole, because I do want it to be modified outside of the given function.

2
  • What do you expect to happen if you can pass an immutable object to a function, which then tries to mutate it? Commented Aug 18, 2020 at 14:54
  • An exception of some kind would be the best, the second best being that that it only locally affects a copy of the object. Either is a solution. Commented Aug 18, 2020 at 14:56

1 Answer 1

4

The short answer is no. There will always be a way to somehow access the object and update it.

Although, there are ways to discourage the mutation of the object. Here are a few.

Pass an immutable object

If some data should not be updated passed some point in the execution of your program, you should make it an immutable object.

my_data = []
populate_my_data(my_data) # this part of the code mutates 'my_data'

my_final_data = tuple(my_data)

Since my_final_data is a tuple, it cannot be mutated. Be aware that mutable objects contained in my_final_data can still be mutated.

Create a view on the object

Instead of passing the object itself, you could provide a view on the object. A view is some instance which provides ways to read your object, but not update it.

Here is how you could define a simple view on a list.

class ListView:
    def __init__(self, data):
        self._data = data

    def __getitem__(self, item):
        return self._data[item]

The above provides an interface for reading from the list with __getitem__, but none to update it.

my_list = [1, 2, 3]
my_list_view = ListView(my_list)

print(my_list_view[0]) # 1
my_list_view[0] = None # TypeError: 'ListView' object does not support item assignment

Once again, it is not completely impossible to mutate your data, one could access it through the field my_list_view._data. Although, this design makes it reasonnably clear that the list should not be mutated at that point.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.