Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Immutable list in Python

I'm trying to make a list which is used throughout the application immutable. I thought wrapping this list in a tuple would do the trick, but it seems that tuple(list) doesn't actually wrap, but copies the list elements.

>>> a = [1, 2, 3, 4]
>>> b = tuple(a)
>>> b
(1, 2, 3, 4)
>>> a[0] = 2
>>> b # was hoping b[0] to be 2
(1, 2, 3, 4)

Is there an easy way of creating a list-backed "view" on this list that is immutable (wrt. operations on this view), but reflects any change that happened to the backing list?

I realise that this question has been asked before, but none of the responses address this view-backing list relationship (in fact some of the comments even suggest that tuples work the way I was hoping they do, but the above snippet suggests otherwise).

like image 755
orange Avatar asked Feb 13 '23 13:02

orange


1 Answers

If you don't want to copy the data, and want to pass an unchangeable "list" around, one way to do so is to create a proxy object, copy of a list, which disables all changing methods, and refer the reading methods to the original list - something along:

class ReadOnlyList(list):
    def __init__(self, other):
        self._list = other

    def __getitem__(self, index):
        return self._list[index]

    def __iter__(self):
        return iter(self._list)

    def __slice__(self, *args, **kw):
        return self._list.__slice__(*args, **kw)

    def __repr__(self):
        return repr(self._list)

    def __len__(self):
        return len(self._list)

    def NotImplemented(self, *args, **kw):
        raise ValueError("Read Only list proxy")

    append = pop = __setitem__ = __setslice__ = __delitem__ = NotImplemented

And, of course, implement whatever other methods you judge necessary, either raising the error (or ignoring the writting instruction) - or acessing the corresponding object in the internal list.

like image 186
jsbueno Avatar answered Feb 16 '23 04:02

jsbueno