Is there a way to return a mutable attribute but protect it from updates?
I have a Calendar
class that uses an internal dict
instance mapping datetime.date
instances to list
instances of event identifiers:
class Calendar:
def __init__(self):
self._dict = {}
def add_event(self, date, event):
if date in self._dict:
self._dict[date].append(event.id)
else:
self._dict[date] = [event.id]
def get_event_ids(self, date):
if date in self._dict:
return self._dict[date]
else:
return []
I would like to protect the calendar from these updates:
calendar = Calendar()
calendar.add_event(date, event)
event_ids = calendar.get_event_ids(date)
event_ids[0] = 42 # updates the mutable list in the calendar
The rationale is that a user might want to update the list of event identifiers returned by the calendar, but he does not expect that doing so will update the calendar.
A read-only property
doesn’t prevent a user from updating the lists.
A solution seems to return copies of the lists. But:
- The
list
instances may become big and theCalendar.get_event_ids
function may be called many times so performing a copy at each call can become inefficient. - In case a user actually wants to change the calendar, returning a copy will mislead him to think he can, because no exception is raised from updates to the
list
instances. - I think a user should be the one deciding to make a copy if he needs to do so.
- I want to know if there is any other way to achieve the same thing.
Another possibility would be to return instances of my own ImmutableList
class. It solves 2 and 3, but not 1 (because I will have to copy the list
instances to initialize ImmutableList
instances) neither 4. Also, it seems like too much work for a very simple concern.
I also know that ‘We are all consenting adults’ and that overprotecting my instance attributes is not Pythonic. But I think my curiosity got the better of me.