El decorador property en Python

Hasta la fecha siempre hemos accedido a los atributos de una clase de forma directa. Es decir, simplemente cuando necesitábamos conocer el valor de un atributo de una clase lo preguntábamos de forma directa, y en le caso, de que quisiéramos modificar ese atributo, lo hacíamos de igual manera. Sin embargo, esto no siempre es lo mas adecuado. Por ejemplo, si queremos controlar que este atributo únicamente tome un rango de valores. Pues bien, para esto está el decorador property en Python.

El decorador property en Python es como contratar a un portero para controlar el acceso a los atributos de una clase, asegurándose de que todo esté en orden y evitando confusiones.

El decorador Property en Python

El decorador property en Python

Entendiendo el decorador property

Imagina que tienes una casa llamada Clase, y dentro de esa casa tienes una habitación llamada Atributo. Ahora, tus amigos, siempre vienen y van a esa habitación sin llamar a la puerta, pueden simplemente entrar y salir a su antojo. A veces, tus amigos pueden desordenar la habitación o dejar cosas fuera de lugar, lo que podría causar confusión. Además, si decides mudarte y cambiar de casa, todos tus amigos tendrían que saber dónde está tu nueva casa y cómo acceder a la habitación adecuada.

Aquí es donde entra en juego el decorador property en Python. Es como si contrataras a un portero llamado property para que controle el acceso a tu habitación «Atributo» en tu casa «Clase». Ahora, tus amigos deben llamar al portero antes de entrar a la habitación y solo pueden acceder a la habitación de una manera específica, siguiendo ciertas reglas que has establecido. El portero se encarga de mantener la habitación ordenada y asegurarse de que todo esté en su lugar.

Además, si decides mudarte y cambiar de casa, solo necesitas informarle a tus amigos la nueva dirección de tu casa, y el portero se asegurará de que sepan cómo acceder a la habitación adecuada en tu nueva casa. ¡Ya no tienes que preocuparte de que tus amigos entren sin permiso o de que dejen cosas fuera de lugar!.

¿Como se utiliza el decorador property?

El decorador @property en Python es una forma elegante de definir atributos de solo lectura en una clase. Permite encapsular la lógica de acceso a un atributo en un método, lo que significa que puedes controlar cómo se accede a ese atributo sin permitir su modificación directa.

Al usar @property, defines un método en tu clase que se comporta como un atributo, pero se accede a él como una función. Este método se llama automáticamente cuando intentas acceder al atributo en cuestión, y puedes personalizar su lógica de retorno. Además, puedes usar @property en combinación con otros decoradores como @setter para definir también la lógica de escritura o modificación del atributo.

Resumiendo, @property te permite crear atributos de solo lectura en tus clases, lo que te permite encapsular la lógica de acceso y modificación de atributos en métodos de tu elección. Es una forma poderosa y elegante de asegurar la integridad y control de tus atributos en tu código Python.

El decorador setter

El decorador @setter en Python es una forma de definir métodos que permiten establecer el valor de un atributo de una clase de manera controlada. Mientras que @property te permite definir atributos de solo lectura, @setter te permite definir la lógica de escritura o modificación de atributos.

Cuando usas @setter, defines un método que se ejecuta automáticamente cuando intentas establecer el valor de un atributo en tu clase. Puedes personalizar la lógica de cómo se establece el valor del atributo, lo que te permite tener un mayor control sobre cómo se modifican los atributos de tu clase. Además, puedes combinar @setter con @property para tener aún más control sobre la lógica de acceso y modificación de atributos en tu clase.

Todo se ve mas claro con un ejemplo

Vamos con un ejemplo del uso de los decoradores @property y @setter, para que veas su potencial,

class Casa:
    def __init__(self, direccion, precio):
        self._direccion = direccion
        self._precio = precio

    @property
    def direccion(self):
        print("Accediendo a la dirección...")
        return self._direccion

    @property
    def precio(self):
        print("Accediendo al precio...")
        return self._precio

    @direccion.setter
    def direccion(self, nueva_direccion):
        print("Actualizando la dirección...")
        self._direccion = nueva_direccion

    @precio.setter
    def precio(self, nuevo_precio):
        print("Actualizando el precio...")
        self._precio = nuevo_precio

    def descripcion(self):
        return f"Casa ubicada en {self._direccion} con precio de {self._precio} euros."


# Creamos una instancia de la clase Casa
mi_casa = Casa("123 Calle Principal", 500000)

# Accedemos a los atributos con el uso del decorador property
print(mi_casa.direccion)  # Salida: Accediendo a la dirección...
# Salida: 123 Calle Principal

print(mi_casa.precio)  # Salida: Accediendo al precio...
# Salida: 500000

# Actualizamos los atributos utilizando los decoradores setter
mi_casa.direccion = "456 Avenida Secundaria"  # Salida: Actualizando la dirección...

mi_casa.precio = 550000  # Salida: Actualizando el precio...

# Accedemos a los atributos actualizados
print(mi_casa.direccion)  # Salida: Accediendo a la dirección...
# Salida: 456 Avenida Secundaria

print(mi_casa.precio)  # Salida: Accediendo al precio...
# Salida: 550000

# Utilizamos el método de la clase
print(mi_casa.descripcion())  # Salida: Casa ubicada en 456 Avenida Secundaria con precio de 550000 euros.

En este ejemplo, la clase Casa tiene dos atributos privados _direccion y _precio. El decorador property se utiliza para definir dos métodos, direccion y precio, que permiten acceder a los valores de estos atributos, pero no modificarlos directamente. Además, se definen dos métodos setter con los decoradores @direccion.setter y @precio.setter para actualizar los valores de los atributos de manera controlada. Finalmente, se utiliza el método descripcion para obtener una descripción de la casa con los valores actualizados de los atributos.

Así, por ejemplo, podemos utilizar el decorador setter, para asegurarnos que el valor que introducimos en un atributo es siempre correcto. En el ejemplo anterior, podemos definir,el método para definir el siguiente valor. Por ejemplo, si quisieramos asegurar que el precio de nuestra casa está entre 300.000 y 600.000, lo podríamos hacer con el decorador setter, de la siguiente manera,

@precio.setter
def precio(self, valor):
    if valor < 300000:
        print("El precio no puede ser menor a 300000.")
    elif valor > 600000:
        print("El precio no puede ser mayor a 600000.")
    else:
        self._precio = valor

O incluso si lo preferimos con excepciones, lo podemos hacer así,

@precio.setter
def precio(self, valor):
    if valor < 300000:
        raise ValueError("El precio no puede ser menor a 300000.")
    elif valor > 600000:
        raise ValueError("El precio no puede ser mayor a 600000.")
    else:
        self._precio = valor

El vídeo

A continuación, lo mismo que te he contado hasta el momento pero en formato vídeo,


Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *