| You are here: Inicio > Inmersión en Python > Ajustes de rendimiento > Optimización de manipulación de cadenas | << >> | ||||
Inmersión en PythonPython de novato a experto |
|||||
El último paso del algoritmo Soundex es rellenar los resultados cortos con ceros y truncar los largos. ¿Cual es la mejor manera de hacerlo?
Esto es lo que tenemos hasta ahora, tomado de soundex/stage2/soundex2c.py:
digits3 = re.sub('9', '', digits2)
while len(digits3) < 4:
digits3 += "0"
return digits3[:4]
Éstos son los resultados de soundex2c.py:
C:\samples\soundex\stage2>python soundex2c.py Woo W000 12.6070768771 Pilgrim P426 14.4033353401 Flingjingwaller F452 19.7774882003
La primera cosa que hemos de considerar es sustituir esa expresión regular con un bucle. Este código es de soundex/stage4/soundex4a.py:
digits3 = ''
for d in digits2:
if d != '9':
digits3 += d
¿Es más rápido soundex4a.py? Pues sí:
C:\samples\soundex\stage4>python soundex4a.py Woo W000 6.62865531792 Pilgrim P426 9.02247576158 Flingjingwaller F452 13.6328416042
Pero espere un momento. ¿Un bucle para eliminar caracteres de una cadena? Podemos usar un simple método de cadenas para eso. Aquí está soundex/stage4/soundex4b.py:
digits3 = digits2.replace('9', '')
¿Es más rápido soundex4b.py? Ésa es una pregunta interesante. Depende de la entrada:
C:\samples\soundex\stage4>python soundex4b.py Woo W000 6.75477414029 Pilgrim P426 7.56652144337 Flingjingwaller F452 10.8727729362
El método de cadena de soundex4b.py es más rápido que el bucle en la mayoría de los casos, pero es ligeramente más lento que soundex4a.py en el caso trivial (de un nombre muy corto). Las optimizaciones de rendimiento no son siempre uniformes; el afinamiento que hace un caso más rápido a veces puede hacer más lentos otros casos. En este caso, la mayoría se beneficia del cambio, así que lo dejaremos como está, pero es un principio importante de recordar.
Por último pero no por ello menos importante, examinemos los dos pasos finales del algoritmo: rellenar los resultados cortos con ceros y truncar los resultados largos a cuatro caracteres. El código que vimos en soundex4b.py hace eso mismo, pero es horriblemente ineficiente. Eche un vistazo a soundex/stage4/soundex4c.py para ver por qué:
digits3 += '000'
return digits3[:4]
¿Par qué necesitamos un bucle while sólo para rellenar el resultado? Sabemos con antelación que vamos a truncar el resultado a cuatro caracteres, y ya sabemos que tenemos al menos un carácter (la letra inicial, que llega sin cambiar de la variable source original). Eso significa que podemos añadir simplemente tres ceros a la salida y luego truncarla. No se ciña totalmente al enunciado exacto del problema; verlo desde un ángulo ligeramente diferente puede llevar a una solución más simple.
¿Cuánta velocidad ganamos en soundex4c.py eliminando el bucle while? Es significativa:
C:\samples\soundex\stage4>python soundex4c.py Woo W000 4.89129791636 Pilgrim P426 7.30642134685 Flingjingwaller F452 10.689832367
Por último, aún hay una cosa que podemos hacer con esas tres líneas de código para acelerarlas: podemos combinarlas en una sola. Eche un vistazo a soundex/stage4/soundex4d.py:
return (digits2.replace('9', '') + '000')[:4]
Poner todo este código en una sola línea en soundex4d.py es ligeramente más rápido que soundex4c.py:
C:\samples\soundex\stage4>python soundex4d.py Woo W000 4.93624105857 Pilgrim P426 7.19747593619 Flingjingwaller F452 10.5490700634
También es bastante menos legible y no gana mucha velocidad. ¿Merece la pena? Espero que haya puesto buenos comentarios. El rendimiento no lo es todo. Sus esfuerzos de optimización siempre deben estar equilibrados frente a las amenazas a la legibilidad y mantenibilidad de los programas.
<< Optimización de operaciones con listas |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
Resumen >> |