1: return self.manos[i].eliminaCoincidencias()
podría escribir:
1: cant = self.manos[i].eliminaCoincidencias()
2: return cant
Ahora ya tiene la oportunidad de mostrar el valor de can’t antes de regresar.
1: return self.manos[i].eliminaCoincidencias()
podría escribir:
1: cant = self.manos[i].eliminaCoincidencias()
2: return cant
Ahora ya tiene la oportunidad de mostrar el valor de can’t antes de regresar.
Sucede. Incluso los mejores programadores se atascan de vez en cuando. A veces trabajan durante tanto tiempo en un programa que no puede ver el error.
Lo que necesita es un par de ojos nuevos.
1: class Fracción:
2: def __init__(self, numerador, denominador=1):
3: self.numerador = numerador
4: self.denominador = denominador
El denominador es opcional. Una Fracción con un solo parámetro representa un numero entero. Si el numerador es n, construimos la fracción n=1.
El siguiente paso es escribir un método str para que imprima las fracciones de forma que tenga sentido. La forma natural de hacerlo es numerador/denominador”:
1: class Fracción:
2: ...
3: def __str__(self):
4: return "%d/%d" % (self.numerador, self.denominador)
Para probar lo que tenemos hasta ahora, lo ponemos en un ¯chero llamado Fracción.py y lo importamos desde el interprete de Python. Entonces creamos un objeto fracción y lo imprimimos.
>;>> from Fracción import fracción
>;>> mortadela = Fracción(5,6)
>;>> print "La fracción es", mortadela
La fracción es 5/6
Como siempre, la función print invoca implícitamente al método str .
class Fracción:
...
def __mul__(self, otro):
return Fracción(self.numerador*otro.numerador,
self.denominador*otro.denominador)
>;>> print Fracción(5,6) * Fracción(3,4)
15/24
Funciona, pero podemos hacerlo mejor! Podemos ampliar el método para manejar la multiplicación por un entero.
Usamos la función type para ver si otro es un entero y convertirlo en una fracción en tal caso.
class Fracción:
...
def __mul__(self, otro):
if type(otro) == type(5):
otro = Fracción(otro)
return Fracción(self.numerador * otro.numerador,
self.denominador * otro.denominador)
Ahora funciona la multiplicación para fracciones y enteros, pero solo si la fracción es el operando de la izquierda.
>;>> print Fracción(5,6) * 4
20/6
>;>> print 4 * Fracción(5,6)
TypeError: __mul__ nor __rmul__ defined for these operands
Para evaluar un operador binario como la multiplicación, Python comprueba primero el operando de la izquierda para ver si proporciona un método __mul__ que soporte el tipo del segundo operando. En este caso, el operador nativo de multiplicación del entero no soporta fracciones.
Después, Python comprueba el segundo operando para ver si provee un método __rmul__ que soporte el tipo del primer operando. En este caso, no hemos provisto el método rmul , por lo que falla.
Por otra parte, hay una forma sencilla de obtener __rmul __:
class Fracción:
...
__rmul__ = __mul__
Esta asignación hace que el método rmul sea el mismo que __mul__ . Si ahora evaluamos 4 * Fracción(5,6), Python llamaría al método __rmul__ del objeto Fracción y le pasara 4 como parámetro:
>;>> print 4 * Fracción(5,6)
20/6
Dado que rmul es lo mismo que __mul__ , y __mul__ puede manejar un parámetro entero, ya esta hecho.
class Fracción:
...
def __add__(self, otro):
if type(otro) == type(5):
otro = Fracción(otro)
return Fracción(self.numerador * otro.denominador +
self.denominador * otro.numerador,
self.denominador * otro.denominador)
__radd__ = __add__
Podemos probar estos métodos con Fracciones y enteros.
>;>> print Fracción(5,6) + Fracción(5,6)
60/36
>;>> print Fracción(5,6) + 3
23/6
>;>> print 2 + Fracción(5,6)
17/6
Los dos primeros ejemplos llaman a __add__ ; el ultimo llama a __radd__ .
1: def mcd (m, n):
2: if m % n == 0:
3: return n
4: else:
5: return mcd(n, m%n)
En la primera l³nea del cuerpo, usamos el operador de modulo para comprobar la divisibilidad. En la ultima l³nea, lo usamos para calcular el resto de la división.
Dado que todas las operaciones que hemos escrito creaban un nuevo objeto Fracción para devolver el resultado, podemos reducir todos los resultados modificando el método de inicialización.
1: class Fracción:
2: def __init__(self, numerador, denominador=1):
3: m = mcd (numerador, denominador)
4: self.numerador = numerador / m
5: self.denominador = denominador / m
Ahora siempre que creemos una Fracción quedara reducida a su forma canoníca:
>;>> Fracción(100,-36)
-25/9
Una característica estupenda de mcd es que si la fracción es negativa, el signo menos siempre se trasladara al numerador.
1: class Fraccion:
2: ...
3: def __cmp__(self, otro):
4: dif = (self.numerador * otro.denominador -
5: otro.numerador * self.denominador)
6: return dif
Si self es mayor que otro, entonces dif sera positivo. Si otro es mayor, entonces dif sera negativo. Si son iguales, dif es cero.
Como ejercicio, termine la implementación de la clase Fracción de forma que pueda manejar resta, división, exponenciación y enteros largos como numerador y denominador.
Creado con WordPress & Tema de Anders Norén