Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Python3 – Modifying Read-Only property – Not throwing AttributeError

I am a Java developer and learning Python. I am using Python 3.10.2. I am trying to understand the read only variables in Python (Similar to final variable in Java), but I am bit confused about the way Python handles things. For example, below is my code.

class Plant:
    def __init__(self, name: str):
        self.__name = name

    @property
    def name(self):
        return self.__name


table_rose = Plant("Table Rose")
print(f"Name of the plant - {table_rose.name}")

#trying to change the name.. Expecting Attribute error in the below line.
table_rose.__name = "Croutons"

print(f"Name of the plant - {table_rose.name}")  #name didnt change..

print(f"Name of the plant - {table_rose.__name}") #It prinits Croutons.. Confusing how python handling things.

The above code prints all three print functions like below, but I was expecting AttributeError

My code output

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Name of the plant - Table Rose
Name of the plant - Table Rose
Name of the plant - Croutons

Can anyone explain why I didnt get any error?

>Solution :

In general, Python doesn’t really do read-only variables like Java does. So when looking at Python code when you might expect a Java class to have a private field, don’t be surprised when everything is just an open variable and not wrapped up in a property decorator.

Anyways, onto your code 🙂

The cause for your confusion is something called name mangling. When you’re inside a class and create an attribute that starts with two underscores (e.g. self.__name), as a feature to allow you to avoid nameclashes when subclassing, Python inserts the class’ name in front (making it actually self._Plant__name under the hood).

But when outside your code, and you reference table_rose.__name, Python doesn’t do the automatic name mangling (as you’re outside the class), so it references just the plain .__name attribute, completely missing the one that you want (called ._Plant__name).

You can see this by using the dir() function. If you pass dir an object, it will return a list of all of that object’s attributes.

>>> dir(table_rose)
['_Plant__name', ... , '__name', ...]

This means that you’re creating a brand new .__name variable with the value 'Croutons', rather than changing the existing one.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading