Ir al contenido principal

Entradas

Mostrando entradas de julio, 2012

A.3.3. Tengo una función o método que no devuelve lo que esperaba.

Si tiene una sentencia return con una expresión compleja no tendrá la oportunidad de imprimir el valor de retorno antes de volver. De nuevo, puede usar una variable temporal. Por ejemplo, en lugar de:   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.

A.3.4. Estoy atascado de verdad y necesito ayuda.

Primero, intente alejarse del computador durante unos minutos. Los computadores emiten unas ondas que afectan al cerebro provocando estos efectos: Frustración y/o furia. Creencias supersticiosas (\el computador me odia") y pensamiento mágico (el programa solo funciona cuando me pongo la gorra hacia atrás"). Programar dando palos de ciego (el empeño de programar escribiendo todos los programas posibles y eligiendo el que hace lo correcto). Si se encuentra afectado por alguno de estos síntomas, levántese y de un paseo. Cuando este calmado, piense en el programa. ¿Que es lo que hace?  ¿Cuales pueden ser las causas de tal comportamiento? ¿Cuando fue la ultima vez que tenia un programa que funcionaba y que fue lo siguiente que hizo? A veces lleva tiempo encontrar un error. Muchas veces encontramos errores cuando estamos lejos del computador y divagamos. Algunos de los mejores lugares para encontrar errores son los trenes, las duchas y la cam

A.3.5. No, de verdad necesito ayuda.

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. Antes de llamar a nadie, asegúrese de que ha agotado las tecnicas explicadas aquí. Su programa debería ser tan simple como sea posible, y usted debería estar trabajando con la entrada mínima que provoca el error. Debería tener sentencias print en los lugares adecuados (y lo que dicen debería ser comprensible). Debería entender el problema lo bastante bien como para describirlo sucintamente. Cuando llame a alguien para que le ayude, asegúrese de darles la información que necesitan: Si hay un mensaje de error, cual es y que parte del programa señala? Que fue lo ultimo que hizo antes de que apareciera el error? Cuales son las ultimas líneas de código que escribió, o cual es el nuevo caso de prueba que no cumple? Que ha intentado hasta ahora y que ha averiguado? Cuando encuentre el error,

Crear un nuevo tipo de datos en Python

Los lenguajes de programación orientados a objetos permiten a los programadores crear nuevos tipos de datos que se comporten de manera muy parecida a los tipos de datos nativos. Exploraremos esta posibilidad construyendo una clase Fracción que funcione de manera muy similar a los tipos numéricos nativos, enteros, enteros largos y flotantes. Las fracciones, también conocidas como números racionales, son valores que pueden expresarse como la proporción entre dos números enteros, tal como 5=6. Al numero superior se se le llama numerador y al inferior se se le llama denominador. Comenzamos definiendo la clase Fracción con un método de inicialización que nos surta de un numerador y un denominador enteros: 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 num

B.1. Multiplicación de fracciones Python

Nos gustaría poder aplicar las operaciones normales de suma, resta, multiplicación y división a las fracciones. Para ello, podemos sobrecargar los operadores matemáticos para los objetos de clase Fracción. Comenzaremos con la multiplicación porque es la mas fácil de implementar. Para multiplicar dos fracciones, creamos una nueva fracción cuyo numerador es el producto de los numeradores de los operandos y cuyo denominador es el producto de los denominadores de los operandos. __mul__ es el nombre que Python utiliza para el método que sobrecarga al operador * : class Fracción: ... def __mul__(self, otro): return Fracción(self.numerador*otro.numerador, self.denominador*otro.denominador) Podemos probar este método calculando el producto de dos fracciones: > ;>> 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 f

B.2. Suma de fracciones Python

La suma es mas complicada que la multiplicación, pero aun es llevadera. La suma de a=b y c=d es la fracción (a*d+c*b)/b*d . Usando como modelo el código de la multiplicación, podemos escribir __add__ y __radd__: 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__ .

B.3. Algoritmo de Euclides Python

En el ejemplo anterior, computamos la suma de 5=6 + 5=6 y obtuvimos 60=36. Es correcto, pero no es la mejor forma de representar la respuesta. Para reducir la fracción a su expresión mas simple, hemos de dividir el numerador y el denominador por el máximo común divisor (MCD) de ambos, que es 12. El resultado sería 5=3. En general, siempre que creamos un nuevo objeto Fracción, deber³amos reducirlo dividiendo el numerador y el denominador por el MCD de ambos. Si la fracción ya esta reducida, el MCD es 1. Euclides de Alejandr³a (aprox. 325{265 a. C.) presento un algoritmo para encontrar el MCD de dos números enfermos m y n: Si n divide a m sin resto, entonces n es el MCD. De lo contrario, el MCD es el MCD de n y el resto de dividir m entre n. Esta definición recursiva puede expresarse concisamente como una función: 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

B.4. Comparar fracciones Python

Supongamos que tenemos dos objetos Fracción, a y b , y evaluamos a == b . La implementación por defecto de == comprueba la igualdad super¯cial, por lo que solo devuelve true si a y b son el mismo objeto. Queremos mas bien devolver verdadero si a y b tienen el mismo valor |eso es,igualdad en profundidad. Hemos de enseñar a las fracciones como compararse entre si. Como vimos en la Sección 15.4, podemos sobrecargar todos los operadores de comparación de una vez proporcionando un método cmp . Por convenio, el método cmp devuelve un numero negativo si self es menor que otro, zero si son lo mismo, y un numero positivo si self es mayor que otro. La forma mas simple de comparar dos fracciones es la multiplicación cruzada. Si a=b > c=d , entonces ad > bc . Con esto en mente, aquí esta el código para cmp : 1: class Fraccion: 2: ... 3: def __cmp__(self, otro): 4: dif = (self.numerador * otro.denominador - 5: otro.nume

B.5. Forzando la máquina

Por supuesto, aun no hemos terminado. Todavía hemos de implementar la resta sobrecargando sub y la división sobrecargando div . Una manera de manejar estas operaciones es implementar la negación sobrecargando negó y la inversión sobrecargando invert . Entonces podemos restar negando el segundo operando y sumando, y podemos dividir invirtiendo el segundo operando y multiplicando. Luego, hemos de suministrar los métodos rsub y rdiv . Desgraciadamente, no podemos usar el mismo truco que usamos para la suma y la multiplicación, porque la resta y la división no son conmutativas. No podemos igualar rsub y rdiv a sub y div . En estas operaciones, el orden de los operandos tiene importancia. Para manejar la negación unitaria, que es el uso del signo menos con un único operando, sobrecargamos el método neg . Podemos computar potencias sobrecargando pow , pero la implementación tiene truco. Si el exponente no es un numero entero podría no ser posible representar el resultado como una F

B.6. Glosario

Máximo común divisor (MCD): El mayor entero positivo que divide al numerador y al denominador de una fracción sin que quede un resto. Reducir : Cambiar la fracción a su forma equivalente con un MCD igual a 1. Negación unitaria: Operación que computa el elemento simétrico aditivo, normalmente denotada con un signo menos delante. Se denomina \unitaria" en contraste con la operación binaria menos, que es la resta.

C.1. Clase Punto Python

1: class Punto: 2: def __init__(self, x=0, y=0): 3: self.x = x 4: self.y = y 5: def __str__(self): 6: return '(' + str(self.x) + ', ' + str(self.y) + ')' 7: def __add__(self, otro): 8: return Punto(self.x + otro.x, self.y + otro.y) 9: def __sub__(self, otro): 10: return Punto(self.x - otro.x, self.y - otro.y) 11: def __mul__(self, otro): 12: return self.x * otro.x + self.y * otro.y 13: def __rmul__(self, otro): 14: return Punto(otro * self.x, otro * self.y) 15: def reverse(self): 16: self.x, self.y = self.y, self.x 17: def delDerechoYDelReves(derecho): 18: from copy import copy 19: reves = copy(derecho) 20: reves.reverse() 21: print str(derecho) + str(reves) DESCARGAR CODIGO FUENTE

C.2. Clase Hora Python

1: class Hora: 2: def __init__(self, horas=0, minutos=0, segundos=0): 3: self.horas = horas 4: self.minutos = minutos 5: self.segundos = segundos 6: def __str__(self): 7: return str(self.horas) + ":" + str(self.minutos) \ 8: + ":" + str(self.segundos) 9: def convierteASegundos(self): 10: minutos = self.horas * 60 + self.minutos 11: segundos = self.minutos * 60 + self.segundos 12: return segundos 13: def incrementa(self, segs): 14: segs = segs + self.segundos 15: self.horas = self.horas + segs/3600 16: segs = segs % 3600 17: self.minutos = self.minutos + segs/60 18: segs = segs % 60 19: self.segundos = segs 20: def haceHora(segs): 21: hora = Hora() 22: hora.horas = segs/3600 23: segs = segs - hora.horas * 36

C.3. Cartas, mazos y juegos Python

1: import random 2: class Carta: 3: listaDePalos = [ "Tr¶eboles" , "Diamantes" , "Corazones" , 4: "Picas" ] 5: listaDeValores = [ "nada" , "As" , "2" , "3" , "4" , "5" , "6" , "7" , 6: "8" , "9" , "10" , "Sota" , "Reina" , "Rey" ] 7: 8: def __init__(self, palo=0, valor=0): 9: self.palo = palo 10: self.valor = valor 11: def __str__(self): 12: return (self.listaDeValores[self.valor] + " de " +\ 13: self.listaDePalos[self.palo]) 14: def __cmp__(self, otro): 15: # controlar el palo 16: if self.palo > otro.palo: return 1 17: if self.palo < otro.palo: return -1 18: # si son del mismo palo, controlar el valor 19