3

I've been working on a school OOP python project and I stumbled upon this problem:

class AList:
    def __init__(self, l):
        self.__a_private_attribute = l

    @property
    def l(self):
        return self.__a_private_attribute


if __name__ == '__main__':
    li = AList([0])
    li.l[0] = "this shouldn't work"
    print(li.l)

The output of this is

["this shouldn't work"]

How am I able to call methods on a list that does only have a getter and no setter. I know that privacy is not a strength of python, but I can't figure out why I can assign items in a list.

I was expecting a AttributeError to be raised by python because I am trying to reassign something without a setter. Does anyone know why am I not raising an Error?

1 Answers1

3

How am I able to call methods on a list that does only have a getter and no setter

Because you never tried to set the list. You got the list, and then changed its first element. This is similar to doing:

some_var = li.l
some_var[0] = "this shouldn't work"

It works because lists are mutable, and you can set elements of the list without reassigning the list itself.

If you tried to do li.l = ["this shouldn't work"], it wouldn't work, because this is actually trying to set li.l

Pranav Hosangadi
  • 23,755
  • 7
  • 44
  • 70
  • Is it bad practice to change an attribute like that? Do other languages prevent you from mutating mutable objects without a setter. It seems like it isn't following rules of encapsulation. – Jakub Watson-Jones Nov 21 '22 at 13:10
  • 1
    @Jakub Python isn't the only language where you can do this. For example, [c# lets you do the same thing](https://dotnetfiddle.net/A4Lsoa). If you want to prevent outside code from modifying the list, you need to return something that is based on your original list, but isn't modifiable, such as a [list iterator in python](/a/2498412/843953), or an [`IEnumerable` or `ReadOnlyList` in c#](/q/2158160/843953) – Pranav Hosangadi Nov 21 '22 at 17:26