Las Python pro­pe­r­ties facilitan la asi­g­na­ción de valores a los atributos de una clase Python. Los métodos getter o setter co­rre­s­po­n­die­n­tes se llaman au­to­má­ti­ca­me­n­te cuando se utiliza una Python property.

¿Qué es exac­ta­me­n­te una Python property y para qué sirve?

Las Python pro­pe­r­ties son una co­n­s­tru­c­ción de pro­gra­ma­ción que los de­sa­rro­lla­do­res pueden utilizar dentro de la pro­gra­ma­ción orientada a objetos con Python. Los pro­gra­ma­do­res pueden uti­li­zar­las 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 pro­pe­r­ties co­n­vie­r­ten los atributos de clase en pro­pie­da­des llamadas “Managed At­tri­bu­tes”.

Además, una Python property im­ple­me­n­ta un tipo de control de acceso: mediante el uso de pro­pie­da­des, se puede ga­ra­n­ti­zar que otros métodos no accedan a los datos del atributo y los mo­di­fi­quen ac­ci­de­n­ta­l­me­n­te.

Consejo

Si utilizas Python para realizar un proyecto web, merece la pena echar un vistazo a la práctica he­rra­mie­n­ta Deploy Now. Te permite construir y desplegar tu código di­re­c­ta­me­n­te a través de GitHub y es, por tanto, una enorme ventaja de efi­cie­n­cia para tu flujo de trabajo.

La función Python property()

Para el uso de pro­pie­da­des, los de­sa­rro­lla­do­res pueden hacer uso de la función Python property(). Se trata de una función in­co­r­po­ra­da que puede uti­li­zar­se sin necesidad de importar módulos adi­cio­na­les. La propia función Python property() está im­ple­me­n­ta­da en el lenguaje de pro­gra­ma­ción C, lo que garantiza un re­n­di­mie­n­to óptimo.

La sintaxis de Python property() es la siguiente:

property(fget=None, fset=None, fdel=None, doc=None)
Python

Los pa­rá­me­tros de la función property() son op­cio­na­les. La siguiente tabla te indica el si­g­ni­fi­ca­do de cada uno de los pa­rá­me­tros:

Parámetro Si­g­ni­fi­ca­do
fget Función que devuelve el valor del atributo (método getter)
fset Función que permite es­ta­ble­cer el valor del atributo (método setter)
fdel Función que es­pe­ci­fi­ca cómo debe su­pri­mi­r­se el atributo
doc Python string, que describe la Property

El decorador de Python Property

El uso de la función property() no es obli­ga­to­rio para trabajar con pro­pie­da­des. A menudo, se recurre a un Python decorator pre­de­fi­ni­do dentro de Python que permite utilizar un método de la clase como propiedad. El lenguaje de pro­gra­ma­ción es co­m­pa­ti­ble con tres de­co­ra­do­res di­fe­re­n­tes en la conocida notación @ para que puedas definir una propiedad:

  • @property: ide­n­ti­fi­ca un método de su clase como una Python Property
  • @nombre-property.setter: es­pe­ci­fi­ca un método setter que establece el valor de una propiedad
  • @nombre-property.deleter: es­pe­ci­fi­ca el método que elimina una propiedad
Nota

Si te interesan los tu­to­ria­les de Python avanzados, te in­te­re­sa­rá echar un vistazo a los si­guie­n­tes artículos:

Ejemplo de Python property

Para vi­sua­li­zar la fu­n­cio­na­li­dad y utilidad de las Python pro­pe­r­ties 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 ar­ti­fi­cial y no tiene utilidad real; sin embargo, es muy adecuado para ilustrar el fu­n­cio­na­mie­n­to de las Python pro­pe­r­ties.

class Perro:
	def __init__(self):
		self._nombre = "Bello"
Python

Puedes ver que al co­n­s­tru­c­tor no se le pasa un parámetro que es­pe­ci­fi­que 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()
Python

Métodos getter y setter

Puedes ampliar tu clase con métodos getter y setter es­pe­cí­fi­cos. Esto tiene sentido por varias razones. Sobre todo, hay que destacar en este punto la facilidad de ma­n­te­ni­mie­n­to del código y la inclusión de fu­n­cio­na­li­da­des adi­cio­na­les. 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 co­rre­s­po­n­die­n­te en un método setter dedicado y se amplía la anterior de­fi­ni­ció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
Python

En 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 es­pe­ci­fi­ca 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 ())
Python

El resultado es el siguiente y, por tanto, también el deseado:

'Lassie'
Nota

A di­fe­re­n­cia de otros lenguajes de pro­gra­ma­ción, Python no sabe di­s­ti­n­guir entre atributos de clase que pueden usarse di­re­c­ta­me­n­te desde el exterior sin métodos getter o setter (en otros lenguajes de pro­gra­ma­ción, estos atributos suelen marcarse como “public”) y aquellos que no deben mo­di­fi­car­se desde el exterior sin más (en otros lenguajes de pro­gra­ma­ción, “private”). Por lo tanto, es una co­n­ve­n­ción comenzar los atributos de nombres de variables que no deben uti­li­zar­se sin métodos getter y setter con un guion bajo.

Función Python property()

Para que puedas pre­s­ci­n­dir 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 de­mo­s­trar­lo, 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)
Python

Como 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 pa­rá­me­tros los métodos getter y setter ya conocidos.

Si ahora creas otro objeto de la clase con el nombre “Snoopy”, re­co­no­ce­rás la di­fe­re­n­cia:

snoopy = Perro()
snoopy.nombre = "Snoopy"
snoopy.nombre
Python

Ahora se puede acceder fá­ci­l­me­n­te a los atributos de la clase con la conocida notación de puntos. El resultado del programa es es­pe­cia­l­me­n­te in­te­re­sa­n­te:

Método setter llamado
Método getter llamado
'Snoopy'

Los métodos getter y setter, aunque no fueron llamados ex­plí­ci­ta­me­n­te, se eje­cu­ta­ron en el momento en que se realizó la asi­g­na­ción o consulta del nombre del objeto “Snoopy” uti­li­za­n­do la notación con punto. Esto es gracias a la Python property.

Python Property decorator

Puedes conseguir el mismo efecto uti­li­za­n­do las funciones de­co­ra­ti­vas ya me­n­cio­na­das. 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
Python

Una vez más, puedes crear un objeto de tu clase y utilizar la notación de puntos para es­ta­ble­cer y leer el atributo “nombre”:

struppi = Perro()
struppi.nombre = "Struppi"
struppi.nombre
Python

El resultado no ha cambiado en co­m­pa­ra­ción con el uso de la función Python property():

Método setter llamado 
Método getter llamado 
'Struppi'
Ir al menú principal