Python language basics 73: class level properties
December 19, 2015 Leave a comment
Introduction
In the previous post we looked at initializers and class level properties. We saw how to add the init method to a class so that we could provide the name property. We also added a second init method so that we could still have an “empty” Person object with no preset name. We also discussed how to attach class level fields to “self” on the fly. The value assigned to those properties was available from another class level method.
In this post we’ll consider class level properties. I felt it was important to provide a post dedicated to that topic because the behaviour of class properties in Python is markedly different from other popular OOP languages such as Java, C#, C++ or VB.NET. At least I was quite surprised when I was first exposed to these class related details in Python.
Class level properties
Recall how we added the _name property to the Person class:
def __init__(self, name): self._name = name
If you’re coming from the world of a strict OOP language such as Java, C# or VB.NET then you might translate the above Python code into something like this:
private String _name; public Person(String name) { this._name = name; }
However, that’s not quite true. First of all “public Person” is a constructor, not an object initializer, but that is not the most interesting detail. The _name variable in the Java example is meant to be visible only within the class, hence the usage of the keyword “private”. The _name variable is private to the Person class. Only the Person class can access it internally. If a Person object is constructed then you cannot directly access its private variables:
Person person = new Person("Mike"); person._name = "Not Mike";
That’s invalid code in Java, it won’t even compile. It’s thank to the protection level “private” in the Person class definition.
There’s none of that in Python. Forget “private”, “public”, “protected” and what you’ve learned about information hiding. The below code is perfectly valid in Python:
person = Person() person._name = "Mr. President" print(person.whats_your_name())
That will print “Mr. President”. That’s right, we’ve accessed the class level variable _name from an external caller.
That’s because all properties, initializers and methods declared at the class level are inherently public in Python. You can’t hide them. If you’re coming from Java, C# etc. then that might sound like a crime to you. In Python the customary way to indicate that the external caller should not modify class level properties is by way of the naming convention applied above: the property name starts with an underscore. That’s how users of the class, such as other programmers will know not to mess with them directly. However, keep in mind, that it’s only a signal. It doesn’t provide the same level of protection as the access modifier “private”.
In the next post we’ll look at the basics of validating class level properties.
Read all Python-related posts on this blog here.