Así como el constructor, __init__
, existen diversos métodos
especiales que, si están definidos en nuestra clase, Python los llamará por nosotros cuando se utilice una instancia en situaciones particulares.
14.4.1. Un método para mostrar objetos
Para mostrar objetos, Python indica que hay que agregarle a la clase
un método especial, llamado __str__
que debe devolver una cadena
de caracteres con lo que queremos mostrar. Ese método se invoca cada
vez que se llama a la función str
.
El método __str__
tiene un solo parámetro, self
.
En nuestro caso decidimos mostrar el punto como un par ordenado, por
lo que escribimos el siguiente método dentro de la clase Punto
:
def __str__(self):
""" Muestra el punto como un par ordenado. """
return "(" + str(self.x) + ", " + str(self.y) + ")"
Una vez definido este método, nuestro punto se mostrará como un par ordenado cuando se necesite una representación de cadenas.
>>> p = Punto(-6,18)
>>> str(p)
'(-6, 18)'
>>> print p
(-6, 18)
Vemos que con str(p)
se obtiene la cadena construida dentro de __str__
,
y que internamente Python llama a __str__
cuando se le pide que imprima una
variable de la clase Punto
.
Nota Muchas de las funciones provistas por Python, que ya hemos utilizado en unidades anteriores, como str
, len
o help
, invocan internamente a los métodos especiales de los objetos.
Es decir que la función str
internamente invoca al método __str__
del objeto que recibe como parámetro. Y de la misma manera len invoca internamente al método __len__
, si es que está definido.
Cuando mediante dir
vemos que un objeto tiene alguno de estos métodos especiales, utilizamos la función de Python correspondiente a ese método especial.
14.4.2. Métodos para operar matemáticamente
Ya hemos visto un método que permitía restar dos puntos. Si bien esta
implementación es perfectamente válida, no es posible usar esa función
para realizar una resta con el operador -
.
>>> p = Punto(3,4)
>>> q = Punto(2,5)
>>> print p - q
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'Punto' and 'Punto'
Si queremos que este operador (o el equivalente para la suma) funcione, será necesario implementar algunos métodos especiales.
def __add__(self, otro):
""" Devuelve la suma de ambos puntos. """
return Punto(self.x + otro.x, self.y + otro.y)
def __sub__(self, otro):
""" Devuelve la resta de ambos puntos. """
return Punto(self.x - otro.x, self.y - otro.y)
El método __add__
es el que se utiliza para el operador +
, el
primer parámetro es el primer operando de la suma, y el segundo
parámetro el segundo operando. Debe devolver una nueva instancia,
nunca modificar la clase actual. De la misma forma, el método
__sub__
es el utilizado por el operador -
.
Ahora es posible operar con los puntos directamente mediante los operadores, en lugar de llamar a métodos:
>>> p = Punto(3,4)
>>> q = Punto(2,5)
>>> print p - q
(1, -1)
>>> print p + q
(5, 9)
De la misma forma, si se quiere poder utilizar cualquier otro operador matemático, será necesario definir el método apropiado.
Nota La posibilidad de definir cuál será el comportamiento de los operadores básicos (como +
, -
, *
, /
), se llama sobrecarga de operadores.
No todos los lenguajes lo permiten, y si bien es cómodo y permite que el código sea más elegante, no es algo esencial a la Programación Orientada a Objetos.
Entre los lenguajes más conocidos que no soportan sobrecarga de operadores están C, Java, Pascal, Objective C. Entre los lenguajes más conocidos que sí soportan sobrecarga de operadores están Python, C++, C#, Perl, Ruby.