| You are here: Inicio > Inmersión en Python > Ajustes de rendimiento | << >> | ||||
Inmersión en PythonPython de novato a experto |
|||||
Los ajustes de rendimiento son tarea de muchos esplendores. El hecho de que Python sea un lenguaje interpretado no significa que no deba preocuparse por la optimización de código. Pero tampoco debe preocuparse demasiado.
Hay tantas trampas en el camino a optimizar el código, que es difícil saber dónde empezar.
Empecemos por aquí: ¿está seguro de que lo necesita? ¿Es tan malo su código? ¿Merece la pena el tiempo de afinarlo? Durante el tiempo de vida de su aplicación, ¿cuánto tiempo va a pasar ese código ejecutándose, comparado al tiempo que habrá de esperar por una base de datos remota o por entrada de un usuario?
Segundo, ¿está seguro de que ya terminó de programar? Optimizar prematuramente es como adornar un pastel a medio hornear. Pasará horas o días (incluso más) optimizando el código para mejorar el rendimiento, sólo para descubrir que no hace lo que necesitaba que hiciera. Es tiempo que se va a la basura.
Esto no quiere decir que la optimización de código no merezca la pena, pero hace falta mirar al sistema completo y decidir cual es la mejor manera de usar su tiempo. Cada minuto que pierda optimizando el código es tiempo que no pasa añadiendo nuevas características, escribiendo documentación, jugando con sus hijos, o escribiendo pruebas unitarias.
Oh sí, pruebas unitarias. Casi se me pasa decir que necesitará un juego completo de pruebas unitarias antes de empezar el ajuste de rendimiento. Lo último que necesita es introducir nuevos fallos mientras juega con los algoritmos.
Con estas consideraciones en mente, veamos algunas técnicas para optimizar código en Python. El código en cuestión es una implementación del algoritmo Soundex. Soundex era un método que usaban a principios del siglo XX para organizar apellidos en categorías en el censo de los Estados Unidos. Agrupaba juntos nombres que sonaban parecido, así que incluso aunque se deletrease mal un nombre, los investigadores tendrían alguna oportunidad de encontrarlo. Soundex se sigue usando hoy día por la misma razón aunque, por supuesto, ahora usamos servidores de bases de datos computerizadas. La mayoría de los servidores de bases de datos incluyen una función Soundex.
Hay muchas variaciones sutiles sobre el algoritmo Soundex. En este capítulo usamos ésta:
Por ejemplo mi nombre, Pilgrim, se convierte en P942695. No tiene duplicados consecutivos así que no haré nada con eso. Ahora eliminamos los 9, dejando P4265. Eso es demasiado largo así que descartamos el carácter de exceso, dejando P426.
Otro ejemplo: Woo pasa a ser W99, que deriva en W9, que a su vez se convierte en W, que hay que rellenar con ceros dejando W000.
Éste es el primer intento de una función Soundex:
Si aún no lo ha hecho, puede descargar éste ejemplo y otros usados en este libro.
import string, re charToSoundex = {"A": "9", "B": "1", "C": "2", "D": "3", "E": "9", "F": "1", "G": "2", "H": "9", "I": "9", "J": "2", "K": "2", "L": "4", "M": "5", "N": "5", "O": "9", "P": "1", "Q": "2", "R": "6", "S": "2", "T": "3", "U": "9", "V": "1", "W": "9", "X": "2", "Y": "9", "Z": "2"} def soundex(source): "convert string to Soundex equivalent" # Soundex requirements: # source string must be at least 1 character # and must consist entirely of letters allChars = string.uppercase + string.lowercase if not re.search('^[%s]+$' % allChars, source): return "0000" # Soundex algorithm: # 1. make first character uppercase source = source[0].upper() + source[1:] # 2. translate all other characters to Soundex digits digits = source[0] for s in source[1:]: s = s.upper() digits += charToSoundex[s] # 3. remove consecutive duplicates digits2 = digits[0] for d in digits[1:]: if digits2[-1] != d: digits2 += d # 4. remove all "9"s digits3 = re.sub('9', '', digits2) # 5. pad end with "0"s to 4 characters while len(digits3) < 4: digits3 += "0" # 6. return first 4 characters return digits3[:4] if __name__ == '__main__': from timeit import Timer names = ('Woo', 'Pilgrim', 'Flingjingwaller') for name in names: statement = "soundex('%s')" % name t = Timer(statement, "from __main__ import soundex") print name.ljust(15), soundex(name), min(t.repeat())
<< Resumen |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
Uso del módulo timeit >> |