Working with Python Classes
Encapsulation is seen as the bundling of data with the methods that operate on that data. It is often accomplished by providing two kinds of methods for attributes: The methods for retrieving or accessing the values of attributes are called getter methods. Getter methods do not change the values of attributes, they just return the values. The methods used for changing the values of attributes are called setter methods.
Public, Private, Protected
There are two ways to restrict the access to class attributes:
protected. First, we can prefix an attribute name with a leading underscore "_". This marks the attribute as protected. It tells users of the class not to use this attribute unless, somebody writes a subclass.
private. Second, we can prefix an attribute name with two leading underscores "__". The attribute is now inaccessible and invisible from outside. It's neither possible to read nor write to those attributes except inside of the class definition itself.
When the Python compiler sees a private attribute, it actually transforms the actual name to _[Class name]__[private attribute name]
. However, this still does not prevent the end-user from accessing the attribute. Thus in Python land, it is more common to use public and protected attribute, write proper docstrings and assume that everyone is a consenting adult, i.e. won't do anything with the protected method unless they know what they are doing.
Class Decorators
@property
The Pythonic way to introduce attributes is to make them public, and not introduce getters and setters to retrieve or change them.@classmethod
To add additional constructor to the class.@staticmethod
To attach functions to classes so people won't misuse them in wrong places.
@Property
Let's assume one day we decide to make a class that could store the temperature in degree Celsius. The temperature will be a private method, so our end-users won't have direct access to it.
The class will also implement a method to convert the temperature into degree Fahrenheit. And we also want to implement a value constraint to the temperature, so that it cannot go below -273 degree Celsius. One way of doing this is to define a getter and setter interfaces to manipulate it.
Instead of that, now the property way. Where we define the @property
and the @[attribute name].setter
.
@classmethod and @staticmethod
@classmethods
create alternative constructors for the class. An example of this behavior is there are different ways to construct a dictionary.
The cls
is critical, as it is an object that holds the class itself. This makes them work with inheritance.
The purpose of @staticmethod is to attach functions to classes. We do this to improve the findability of the function and to make sure that people are using the function in the appropriate context.
For those interested, the following link contains a much more in-depth introduction into @classmethod and @staticmethod. Blog: Python's Instance, Class, and Static Methods Demystified