Métodos especiales de las Clases en Python

Python cuenta con una serie de métodos especiales incluidos que invoca por nosotros en circunstancias particulares o cuando se usa una sintaxis específica, con el fin de emular cierto tipo de funcionalidades. Supongamos que tenemos nuestra clase que cuenta con un diccionario con datos de un cliente.

 >>> class Clientes:
 ... def __init__(self, dict=None):
 ... self.data = {}
 ... if dict is not None:
 ... self.update(dict)
 ... def update(self, dict=None):
 ... self.data.update(dict)
 ... def clear(self): self.data.clear()
 ... def keys(self): return self.data.keys()
 ... def items(self): return self.data.items()
 ... def values(self): return self.data.values()
 ... def getvalue(self, key): return self.data[key]
 ...
 >>>
 >>> c = Clientes({'nombre':'Jorge', 'apellidos':'Toro', 'nit':'100244235', 'cargo':'aseador', 'telefono':None})
 >>> c
 <__main__.Clietes instance at 0xb743d16c>
 >>> c.keys()
 ['apellidos', 'nombre', 'telefono', 'nit', 'cargo']
 >>> c.values()
 ['Toro', 'Jorge', None, '100244235', 'aseador']
 >>> c.items()
 [('apellidos', 'Toro'), ('nombre', 'Jorge'), ('telefono', None), ('nit', '100244235'), ('cargo', 'aseador')]
 >>> # Obtener el cargo del cliente
 ... c.getvalue('cargo')
 'aseador'
 >>>

Los métodos especiales nos permiten realizar ciertas acciones o comportamientos diferentes a solo llamar métodos. En lugar de usar un método como “getvalue()”, puede hacerse con una sintaxis que no incluya una invocación explícita a métodos. Aquí es donde entran los “métodos especiales”, ya que nos proporcionan este tipo de sintaxis especial, convirtiendo la “sintaxis que no llama a métodos” en “llamadas a métodos”.

Método especial __getitem__:

Como sería si yo quisiera obtener un “valor” de mi cliente (objeto Clientes()), como se obtiene en un diccionario normalmente (valor=diccionario[clave]). Intentémoslo con el método getvalue().

 >>> c.getvalue['cargo']
 Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 TypeError: 'instancemethod' object is unsubscriptable
 >>> c['cargo']
 Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 AttributeError: Clietes instance has no attribute '__getitem__'
 >>>

Para lograr este comportamiento existe el método especial __getitem__, que llama por nosotros al método tal como lo conocemos (c.getvalue(key)). Redefinamos nuestra clase “Clientes”:

 >>> class Clientes:
 ... def __init__(self, dict=None):
 ... self.data = {}
 ... if dict is not None:
 ... self.update(dict)
 ... def update(self, dict=None):
 ... self.data.update(dict)
 ... def clear(self): self.data.clear()
 ... def keys(self): return self.data.keys()
 ... def items(self): return self.data.items()
 ... def values(self): return self.data.values()
 ... def __getitem__(self, key): return self.data[key]
 ...
 >>>
 >>> c = Clientes({'nombre':'Jorge', 'apellidos':'Toro', 'nit':'100244235', 'cargo':'aseador', 'telefono':None})
 >>> c['cargo']
 'aseador'
 >>>

Este comportamiento es igual a la sintaxis usada normalmente para obtener un valor de un diccionario. Para lograr este comportamiento Python convierte internamente la llamada c[key], en una llamada c.__getitem__(key). Por eso es __getitem__ es un método especial; no sólo puede invocarlo usted, sino que puede hacer que Python lo invoque usando la sintaxis adecuada. Igualmente podemos llamarlo como si se tratara de un método normal (Pero esta no es la idea).

 >>> c.__getitem__('cargo')
 'aseador'
 >>>

Método especial __setitem__:

Sí, como ya se pueden imaginar, este método especial nos sirve para reemplazar un “valor”, en nuestro objeto “Clientes”, como si de un diccionario se tratara.

 >>> class Clientes:
 ... def __init__(self, dict=None):
 ... self.data = {}
 ... if dict is not None:
 ... self.update(dict)
 ... def update(self, dict=None):
 ... self.data.update(dict)
 ... def clear(self): self.data.clear()
 ... def keys(self): return self.data.keys()
 ... def items(self): return self.data.items()
 ... def values(self): return self.data.values()
 ... def __getitem__(self, key): return self.data[key]
 ... def __setitem__(self, key, item): self.data[key] = item
 ...
 >>> c = Clientes({'nombre':'Jorge', 'apellidos':'Toro', 'nit':'100244235', 'cargo':'aseador', 'telefono':None})
 >>> c["cargo"] = 'lava platos'
 >>> c["cargo"]
 'lava platos'
 >>> c.items()
 [('apellidos', 'Toro'), ('nombre', 'Jorge'), ('telefono', None), ('nit', '100244235'), ('cargo', 'lava platos')]
 >>>

Estas llamadas parecen la sintaxis normal de un diccionario, excepto que “c” es realmente una clase que intenta por todos los medios aparentar ser un diccionario.

 

Autor: Jolth

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s