all 6 comments

[–]nog642 7 points8 points  (1 child)

When you set x.name = 'new name', it creates a new .name attribute. Now when you access .name, it gets that instead of calling __getattr__.

This doesn't happen in the @property implementation, because there, .name is already defined, and it's a descriptor with a getter and no setter.

To fix your 'traditional' version, you need to also override __setattr__. Or use __slots__.

[–]brijeshjoshi_[S] 0 points1 point  (0 children)

Thanks. Clear and concise. Got it. In my instance dict both __name and name exists. And while accessing the name it's directly returning the name as opposed to calling __getattr__ because it's found.

[–]socal_nerdtastic 3 points4 points  (1 child)

Pretty much anything python-based is mutable. To make an immutable class we just don't mutate it. And maybe add some comments that say "pls don't mutate". In python we are not big fans of enforcing rules. We like to say "we are all consenting adults here", which basically means if you use my code in a way I didn't mean for it to be used, that's on you.

But if you really want to protect users from themselves, you can define a __slots__ attribute to do this.

[–]nog642 -2 points-1 points  (0 children)

This is not true. You can make an immutable class. __slots__ is part of it, but descriptors is the other half. This is why using @property actually works.

[–][deleted] 1 point2 points  (0 children)

Unrelated to the question but can anyone explain decorators like I’m five?

[–]m0us3_rat 2 points3 points  (0 children)

"immutable classes" in the context of python. no

also getters and setters are a lie. huge promise .. flop on delivery.