¿Existe algún método eficiente de concatenación de cadenas masivas en Python (como StringBuilder en C # o StringBuffer en Java)? Encontré los siguientes métodos aquí :
- Concatenación simple usando
+
- Usando la lista de cadenas y el
join
método - Usando
UserString
desde elMutableString
módulo - Usando la matriz de caracteres y el
array
módulo - Usando
cStringIO
desde elStringIO
módulo
Pero, ¿qué usan o sugieren los expertos y por qué?
f''
cadenas de formato que serán más rápidas que cualquier alternativa en versiones anteriores de Python.Respuestas:
Te puede interesar esto: una anécdota de optimización de Guido. Aunque vale la pena recordar también que este es un artículo antiguo y es anterior a la existencia de cosas como
''.join
(aunque supongo questring.joinfields
es más o menos lo mismo)En virtud de eso, el
array
módulo puede ser más rápido si puede resolver su problema. Pero''.join
probablemente sea lo suficientemente rápido y tenga la ventaja de ser idiomático y, por lo tanto, más fácil de entender para otros programadores de Python.Finalmente, la regla de oro de la optimización: no optimices a menos que sepas que lo necesitas y mide en lugar de adivinar.
Puede medir diferentes métodos usando el
timeit
módulo. Eso le puede decir cuál es el más rápido, en lugar de extraños al azar en Internet haciendo conjeturas.fuente
.join()
? La pregunta principal es, ¿a) crea una copia de la cadena para la concatenación (similar as = s + 'abc'
), que requiere O (n) tiempo de ejecución, o b) simplemente agrega a la cadena existente sin crear una copia, que requiere O (1) ?''.join(sequenceofstrings)
es lo que generalmente funciona mejor: más simple y más rápido.fuente
''.join(sequence)
idioma. Es especialmente útil producir listas separadas por comas:', '.join([1, 2, 3])
da la cadena'1, 2, 3'
."".join(chr(x) for x in xrange(65,91))
--- en este caso, el argumento para unirse es un iterador, creado a través de una expresión generadora. No hay una lista temporal que se construya.Python 3.6 cambió el juego para la concatenación de cadenas de componentes conocidos con Literal String Interpolation .
Dado el caso de prueba de la respuesta de mkoistinen , tener cadenas
Los contendientes son
f'http://{domain}/{lang}/{path}'
- 0.151 µs'http://%s/%s/%s' % (domain, lang, path)
- 0.321 µs'http://' + domain + '/' + lang + '/' + path
- 0.356 µs''.join(('http://', domain, '/', lang, '/', path))
- 0.249 µs (observe que construir una tupla de longitud constante es un poco más rápido que construir una lista de longitud constante).Por lo tanto, actualmente el código más corto y hermoso posible es también el más rápido.
En las versiones alfa de Python 3.6, la implementación de
f''
cadenas fue la más lenta posible: en realidad, el código de bytes generado es prácticamente equivalente al''.join()
caso de llamadas innecesarias a lasstr.__format__
que sin argumentos simplemente regresaríanself
sin cambios. Estas ineficiencias se abordaron antes de 3.6 final.La velocidad se puede contrastar con el método más rápido para Python 2, que es la
+
concatenación en mi computadora; y eso toma 0.203 µs con cadenas de 8 bits, y 0.259 µs si las cadenas son todas Unicode.fuente
Depende de lo que estés haciendo.
Después de Python 2.5, la concatenación de cadenas con el operador + es bastante rápida. Si solo está concatenando un par de valores, usar el operador + funciona mejor:
Sin embargo, si está armando una cadena en un bucle, es mejor usar el método de unión de lista:
... pero tenga en cuenta que debe juntar un número relativamente alto de cadenas antes de que la diferencia sea notable.
fuente
Según la respuesta de John Fouhy, no optimices a menos que tengas que hacerlo, pero si estás aquí y haces esta pregunta, puede ser precisamente porque tienes que hacerlo . En mi caso, necesitaba ensamblar algunas URL de variables de cadena ... rápido. Noté que nadie (hasta ahora) parece estar considerando el método de formato de cadena, por lo que pensé en probarlo y, sobre todo por un leve interés, pensé en tirar el operador de interpolación de cadena allí para una buena medición. Para ser honesto, no pensé que ninguno de estos se apilara a una operación directa '+' o un '' .join (). ¿Pero adivina que? En mi sistema Python 2.7.5, el operador de interpolación de cadenas los gobierna a todos y string.format () es el de peor desempeño:
Los resultados:
Si uso un dominio más corto y una ruta más corta, la interpolación sigue ganando. Sin embargo, la diferencia es más pronunciada con cadenas más largas.
Ahora que tenía un buen script de prueba, también probé en Python 2.6, 3.3 y 3.4, aquí están los resultados. ¡En Python 2.6, el operador plus es el más rápido! En Python 3, unirse gana. Nota: estas pruebas son muy repetibles en mi sistema. Entonces, 'plus' siempre es más rápido en 2.6, 'intp' siempre es más rápido en 2.7 y 'join' siempre es más rápido en Python 3.x.
Lección aprendida:
tl; dr:
fuente
f'http://{domain}/{lang}/{path}'
.format()
tiene tres formas, con el fin de rápido a lento:"{}".format(x)
,"{0}".format(x)
,"{x}".format(x=x)
depende en gran medida de los tamaños relativos de la nueva cadena después de cada nueva concatenación. Con el
+
operador, para cada concatenación se crea una nueva cadena. Si las cadenas intermedias son relativamente largas, se+
vuelven cada vez más lentas porque se está almacenando la nueva cadena intermedia.Considere este caso:
Resultados
1 0.00493192672729
2 0.000509023666382
3 0.00042200088501
4 0.000482797622681
En el caso de 1 y 2, agregamos una cadena grande y join () realiza aproximadamente 10 veces más rápido. En los casos 3 y 4, agregamos una cadena pequeña y '+' funciona un poco más rápido
fuente
Me encontré con una situación en la que necesitaba tener una cadena de tamaño desconocido. Estos son los resultados de referencia (python 2.7.3):
Esto parece mostrar que '+ =' es el más rápido. Los resultados del enlace skymind están un poco desactualizados.
(Me doy cuenta de que el segundo ejemplo no está completo, la lista final necesitaría unirse. Sin embargo, esto muestra que simplemente preparar la lista lleva más tiempo que la cadena concat.)
fuente
Un año después, probemos la respuesta de mkoistinen con python 3.4.3:
Nada ha cambiado. Unirse sigue siendo el método más rápido. Sin embargo, dado que intp es posiblemente la mejor opción en términos de legibilidad, es posible que desee utilizar intp.
fuente
Inspirado por los puntos de referencia de @ JasonBaker, aquí hay uno simple que compara 10
"abcdefghijklmnopqrstuvxyz"
cadenas, que muestra que.join()
es más rápido; incluso con este pequeño aumento en las variables:Cadena
Unirse
fuente
Para un pequeño conjunto de cadenas cortas (es decir, 2 o 3 cadenas de no más de unos pocos caracteres), más aún es mucho más rápido. Usando el maravilloso script de mkoistinen en Python 2 y 3:
Entonces, cuando su código está haciendo una gran cantidad de pequeñas concatenaciones separadas, más es la forma preferida si la velocidad es crucial.
fuente
Probablemente "nuevas cadenas f en Python 3.6" es la forma más eficiente de concatenar cadenas.
Usando% s
Usando .format
Usando f
Fuente: https://realpython.com/python-f-strings/
fuente