Python property: cómo llamar implícitamente a métodos getter y setter
Las Python properties facilitan la asignación de valores a los atributos de una clase Python. Los métodos getter o setter correspondientes se llaman automáticamente cuando se utiliza una Python property.
¿Qué es exactamente una Python property y para qué sirve?
Las Python properties son una construcción de programación que los desarrolladores pueden utilizar dentro de la programación orientada a objetos con Python. Los programadores pueden utilizarlas para definir métodos a los que se puede acceder del mismo modo que a los atributos. Esto permite un acceso más intuitivo a los atributos de una clase y también elimina la necesidad de llamar a métodos setter y getter dedicados. Las Python properties convierten los atributos de clase en propiedades llamadas “Managed Attributes”.
Además, una Python property implementa un tipo de control de acceso: mediante el uso de propiedades, se puede garantizar que otros métodos no accedan a los datos del atributo y los modifiquen accidentalmente.
Si utilizas Python para realizar un proyecto web, merece la pena echar un vistazo a la práctica herramienta Deploy Now. Te permite construir y desplegar tu código directamente a través de GitHub y es, por tanto, una enorme ventaja de eficiencia para tu flujo de trabajo.
La función Python property()
Para el uso de propiedades, los desarrolladores pueden hacer uso de la función Python property(). Se trata de una función incorporada que puede utilizarse sin necesidad de importar módulos adicionales. La propia función Python property() está implementada en el lenguaje de programación C, lo que garantiza un rendimiento óptimo.
La sintaxis de Python property() es la siguiente:
property(fget=None, fset=None, fdel=None, doc=None)
PythonLos parámetros de la función property() son opcionales. La siguiente tabla te indica el significado de cada uno de los parámetros:
Parámetro | Significado |
---|---|
fget | Función que devuelve el valor del atributo (método getter) |
fset | Función que permite establecer el valor del atributo (método setter) |
fdel | Función que especifica cómo debe suprimirse el atributo |
doc | Python string, que describe la Property |
El decorador de Python Property
El uso de la función property() no es obligatorio para trabajar con propiedades. A menudo, se recurre a un Python decorator predefinido dentro de Python que permite utilizar un método de la clase como propiedad. El lenguaje de programación es compatible con tres decoradores diferentes en la conocida notación @ para que puedas definir una propiedad:
- @property: identifica un método de su clase como una Python Property
- @nombre-property.setter: especifica un método setter que establece el valor de una propiedad
- @nombre-property.deleter: especifica el método que elimina una propiedad
Si te interesan los tutoriales de Python avanzados, te interesará echar un vistazo a los siguientes artículos:
Ejemplo de Python property
Para visualizar la funcionalidad y utilidad de las Python properties en igual medida, un ejemplo de código detallado será de ayuda. En el siguiente fragmento de código, primero se crea una clase llamada “perro” con el atributo “_nombre”. Es cierto que este ejemplo es muy artificial y no tiene utilidad real; sin embargo, es muy adecuado para ilustrar el funcionamiento de las Python properties.
class Perro:
def __init__(self):
self._nombre = "Bello"
PythonPuedes ver que al constructor no se le pasa un parámetro que especifique el nombre de nuestro perro. En su lugar, el nombre del perro se establece en el valor “Bello” por defecto. Así que puedes crear un objeto de la clase con la siguiente línea de código, por ejemplo:
perro = Perro()
PythonMétodos getter y setter
Puedes ampliar tu clase con métodos getter y setter específicos. Esto tiene sentido por varias razones. Sobre todo, hay que destacar en este punto la facilidad de mantenimiento del código y la inclusión de funcionalidades adicionales. Dado que los nombres son por defecto cadenas, también se pretende estar seguro en nuestra clase de que un nombre se pasa realmente en forma de cadena. Para ello, se escribe la lógica de la función correspondiente en un método setter dedicado y se amplía la anterior definición de nuestra clase:
class Perro:
def __init__(self):
self._nombre = "Bello"
def getNombre(self):
return self._nombre
def setNombre(self, nombre):
if isinstance(nombre, str):
self._nombre = nombre
else:
return
PythonEn el método setter llamado “setNombre”, una sentencia if else de Python comprueba si el parámetro pasado es una cadena. Si es así, se establece el nombre, de lo contrario no ocurre nada.
También se especifica un método getter que devuelve el nombre del perro.
Se puede crear un objeto de la clase con el nombre “Lassie” de la siguiente manera:
lassie = Perro()
lassie.setNombre("Lassie")
print(lassie.getNombre ())
PythonEl resultado es el siguiente y, por tanto, también el deseado:
'Lassie'
A diferencia de otros lenguajes de programación, Python no sabe distinguir entre atributos de clase que pueden usarse directamente desde el exterior sin métodos getter o setter (en otros lenguajes de programación, estos atributos suelen marcarse como “public”) y aquellos que no deben modificarse desde el exterior sin más (en otros lenguajes de programación, “private”). Por lo tanto, es una convención comenzar los atributos de nombres de variables que no deben utilizarse sin métodos getter y setter con un guion bajo.
Función Python property()
Para que puedas prescindir de una llamada explícita a una función si quieres cambiar o averiguar el nombre de tu perro Python, ahora haz uso de una Python property. Para demostrarlo, también se incluye una sentencia print en cada uno de nuestros métodos getter y setter.
class Perro:
def __init__(self):
self._nombre = "Bello"
def getNombre(self):
print("Método getter llamado")
return self._nombre
def setNombre(self, nombre):
if isinstance(nombre, str):
self._nombre = nombre
print("Método setter llamado")
else:
return
nombre = property(getNombre, setNombre)
PythonComo puedes ver, todo lo que se ha tenido que hacer para llamar a la función property() ha sido crear un nuevo atributo llamado “nombre” (esta vez sin guion bajo inicial, porque gracias a la Python property se puede llamar desde fuera sin más) y asignarle el resultado de nuestra llamada a la función. La función property() recibe como parámetros los métodos getter y setter ya conocidos.
Si ahora creas otro objeto de la clase con el nombre “Snoopy”, reconocerás la diferencia:
snoopy = Perro()
snoopy.nombre = "Snoopy"
snoopy.nombre
PythonAhora se puede acceder fácilmente a los atributos de la clase con la conocida notación de puntos. El resultado del programa es especialmente interesante:
Método setter llamado
Método getter llamado
'Snoopy'
Los métodos getter y setter, aunque no fueron llamados explícitamente, se ejecutaron en el momento en que se realizó la asignación o consulta del nombre del objeto “Snoopy” utilizando la notación con punto. Esto es gracias a la Python property.
Python Property decorator
Puedes conseguir el mismo efecto utilizando las funciones decorativas ya mencionadas. En este caso, el código de ejemplo sería así (ten en cuenta que los dos métodos que se decoran ahora deben tener el mismo nombre):
class Perro:
def __init__(self):
self._nombre = "Bello"
@property
def nombre(self):
print("Método setter llamado")
return self._nombre
@nombre.setter
def nombre(self, nombre):
if isinstance(nombre, str):
self._nombre = nombre
print("Método getter llamado")
else:
return
PythonUna vez más, puedes crear un objeto de tu clase y utilizar la notación de puntos para establecer y leer el atributo “nombre”:
struppi = Perro()
struppi.nombre = "Struppi"
struppi.nombre
PythonEl resultado no ha cambiado en comparación con el uso de la función Python property():
Método setter llamado
Método getter llamado
'Struppi'