...

/

An Application of Descriptors

An Application of Descriptors

Learn how to apply descriptors in real situations.

Now that we have seen what descriptors are, how they work, and what the main ideas behind them are, we can see them in action. Let’s explore some situations that can be elegantly addressed through descriptors.

An application of descriptors

We'll start with a simple example that works but will lead to some code duplication. Later on, we'll devise a way of abstracting the repeated logic into a descriptor, which will address the duplication problem, and we'll observe that the code on our client classes will reduce drastically.

A first attempt without using descriptors

The problem we want to solve now is that we have a regular class with some attributes, but we wish to track all of the different values a particular attribute has over time, for example, in a list. The first solution that comes to mind is to use a property, and every time a value is changed for that attribute in the setter method of the property, we add it to an internal list that will keep this trace as we want it.

Creating a class that represents a traveler

Imagine that our class represents a traveler in our application that has a current city, and we want to keep track of all the cities that user has visited throughout the running of the program. The code below is a possible implementation that addresses these requirements. We can easily check that this code works according to our requirements, as we do below on lines 28–33:

Press + to interact
class Traveler:
"""A person visiting several cities.
We wish to track the path of the traveller, as he or she is visiting each
new city.
"""
def __init__(self, name, current_city):
self.name = name
self._current_city = current_city
self._cities_visited = [current_city]
@property
def current_city(self):
return self._current_city
@current_city.setter
def current_city(self, new_city):
if new_city != self._current_city:
self._cities_visited.append(new_city)
self._current_city = new_city
@property
def cities_visited(self):
return self._cities_visited
if __name__ == "__main__":
alice = Traveler("Alice", "Barcelona")
alice.current_city = "Paris"
alice.current_city = "Brussels"
alice.current_city = "Amsterdam"
print(alice.cities_visited)

Considerations to take into account regarding our class

So far, this is all we need and nothing else ...