Tutorial

Python @property Decorator

4 min read

Python @property decorator allows us to define methods in a class that can be accessed like attributes, providing a clean and intuitive way to encapsulate the logic behind attribute access and modification.

When we define a property using python  @property decorator, we essentially create a getter method that can be accessed without invoking it explicitly as a method. It allows us to define a computed or derived attribute that is dynamically calculated based on other attributes of the class.

Here’s an example to illustrate the usage of Python  @property decorator:

class Circle:
    def __init__(self, radius):
        self.radius = radius
    
    @property
    def diameter(self):
        return self.radius * 2
    
    @property
    def area(self):
        return 3.14159 * self.radius**2

Here, the Circle class has two properties: diameter and area.

These properties are defined using the @property decorator. The diameter property returns the diameter of the circle based on the radius attribute, and the area property calculates the area of the circle.

Class Using Getters and Setters in Python

class Person:
    def __init__(self, name, age):
        self._name = name
        self._age = age

    def get_name(self):
        return self._name

    def set_name(self, name):
        self._name = name

    def get_age(self):
        return self._age

    def set_age(self, age):
        if age >= 0:
            self._age = age
        else:
            raise ValueError("Age must be a non-negative value.")

person = Person("Alice", 25)

print(person.get_name())  # Output: Alice
print(person.get_age())   # Output: 25

person.set_name("Bob")
person.set_age(30)

print(person.get_name())  # Output: Bob
print(person.get_age())   # Output: 30

Here, the Person class has _name and _age attributes, which are considered as internal attributes. We define getter and setter methods for each attribute, following the naming convention of get_<attribute> and set_<attribute>.

Using getters and setters, we can control the access and modification of attributes and add additional logic if needed.

For example, in the set_age method, we include a validation check to ensure that the age is a non-negative value.

By utilizing getters and setters, we have better control over the attribute access and modification process, allowing us to enforce constraints, perform validations, or trigger additional actions whenever an attribute is accessed or modified.

Class Without Using Getters and Setters in Python

In Python, we can define a class without explicit getters and setters. By default, attributes of a class are accessible and modifiable directly.

Here’s a Python example of Class Without Using Getters and Setters:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

person = Person("Alice", 25)

print(person.name)  # Output: Alice
print(person.age)   # Output: 25

person.age = 30
print(person.age)   # Output: 30

Here, we have a Person class with name and age attributes.

These attributes can be accessed and modified directly without the need for explicit getters and setters.

However, it’s important to note that by directly accessing and modifying attributes, we lose the ability to add any additional logic or validation during attribute access or modification.

This can make it challenging to enforce certain constraints or perform specific actions whenever an attribute is accessed or modified.

The Property Class & The @property Decorator in Python

In Python, the property class and @property decorator are used to create properties within a class. They provide a convenient way to define attribute accessors (getters), attribute mutators (setters), and attribute deleters, allowing for fine-grained control over attribute behavior.

  • property class: The property class is a built-in Python class that allows us to define properties within a class. It provides methods such as getter(), setter(), and deleter() to define the behavior associated with attribute access, modification, and deletion.

Here’s an example of Property Class & The @property Decorator in Python-

class Circle:
    def __init__(self, radius):
        self._radius = radius

    def get_radius(self):
        return self._radius

    def set_radius(self, value):
        self._radius = value

    def del_radius(self):
        del self._radius

    radius = property(get_radius, set_radius, del_radius)

Here, the Circle class defines a property called radius using the property class. The get_radius(), set_radius(), and del_radius() methods define the corresponding behavior associated with attribute access, modification, and deletion. By assigning the property() call to the radius attribute, we create the property.

  • @property decorator: The @property decorator provides a more concise and elegant way to define properties in Python classes. By decorating a method with @property, it becomes a getter for a property. Here’s an example:
class Circle:
    def __init__(self, radius):
        self._radius = radius

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        self._radius = value

    @radius.deleter
    def radius(self):
        del self._radius

Here, in the updated Circle class, the radius method is decorated with @property, making it a getter for the radius property.

Similarly, the @radius.setter decorator is used to define a setter, and @radius.deleter is used to define a deleter for the radius property.

With the @property decorator, we can access and modify the radius attribute as if it were a regular attribute, without needing to call getter or setter methods explicitly.

Behind the scenes, the decorated methods are automatically invoked when accessing or modifying the property.