En Python, el dónde y cuándo usar la concatenación de cadenas frente a la sustitución de cadenas se me escapa. Dado que la concatenación de cuerdas ha experimentado grandes aumentos en el rendimiento, ¿es esta (cada vez más) una decisión estilística en lugar de práctica?
Para un ejemplo concreto, ¿cómo se debe manejar la construcción de URI flexibles?
DOMAIN = 'http://stackoverflow.com'
QUESTIONS = '/questions'
def so_question_uri_sub(q_num):
return "%s%s/%d" % (DOMAIN, QUESTIONS, q_num)
def so_question_uri_cat(q_num):
return DOMAIN + QUESTIONS + '/' + str(q_num)
Editar: También ha habido sugerencias sobre cómo unir una lista de cadenas y usar la sustitución con nombre. Estas son variantes del tema central, que es, ¿de qué manera es la forma correcta de hacerlo y en qué momento? ¡Gracias por las respuestas!
python
string
string-concatenation
gotgenes
fuente
fuente
Respuestas:
La concatenación es (significativamente) más rápida según mi máquina. Pero estilísticamente, estoy dispuesto a pagar el precio de la sustitución si el rendimiento no es crítico. Bueno, y si necesito formatear, no hay necesidad de hacer la pregunta ... no hay otra opción que usar interpolación / plantilla.
fuente
No se olvide de la sustitución con nombre:
fuente
¡Tenga cuidado con la concatenación de cadenas en un bucle! El costo de la concatenación de cadenas es proporcional a la longitud del resultado. El bucle te lleva directamente a la tierra de N-squared. Algunos lenguajes optimizarán la concatenación a la cadena asignada más recientemente, pero es arriesgado contar con el compilador para optimizar su algoritmo cuadrático hasta lineal. Es mejor usar la primitiva (
join
?) Que toma una lista completa de cadenas, hace una sola asignación y las concatena todas de una vez.fuente
"Como la concatenación de cuerdas ha experimentado grandes aumentos en el rendimiento ..."
Si el rendimiento importa, es bueno saberlo.
Sin embargo, los problemas de rendimiento que he visto nunca se han reducido a operaciones con cadenas. En general, me he metido en problemas con las operaciones de E / S, clasificación y O ( n 2 ) que son los cuellos de botella.
Hasta que las operaciones de cadena sean los limitadores del rendimiento, me quedaré con las cosas que son obvias. Principalmente, eso es sustitución cuando es una línea o menos, concatenación cuando tiene sentido y una herramienta de plantilla (como Mako) cuando es grande.
fuente
Lo que desea concatenar / interpolar y cómo desea formatear el resultado debe impulsar su decisión.
La interpolación de cadenas le permite agregar formato fácilmente. De hecho, su versión de interpolación de cadenas no hace lo mismo que su versión de concatenación; en realidad, agrega una barra diagonal adicional antes del
q_num
parámetro. Para hacer lo mismo, tendría que escribirreturn DOMAIN + QUESTIONS + "/" + str(q_num)
ese ejemplo.La interpolación facilita el formateo de números;
"%d of %d (%2.2f%%)" % (current, total, total/current)
sería mucho menos legible en forma de concatenación.La concatenación es útil cuando no tiene un número fijo de elementos para encadenar.
Además, sepa que Python 2.6 presenta una nueva versión de interpolación de cadenas, llamada plantilla de cadenas :
La plantilla de cadenas está programada para reemplazar eventualmente la interpolación porcentual, pero eso no sucederá durante bastante tiempo, creo.
fuente
Solo estaba probando la velocidad de diferentes métodos de concatenación / sustitución de cadenas por curiosidad. Una búsqueda en Google sobre el tema me trajo aquí. Pensé que publicaría los resultados de mi prueba con la esperanza de que pudiera ayudar a alguien a decidir.
... Después de ejecutar
runtests((percent_, format_, format2_, concat_), runs=5)
, descubrí que el método% era aproximadamente el doble de rápido que los demás en estas pequeñas cadenas. El método concat siempre fue el más lento (apenas). Hubo diferencias muy pequeñas al cambiar las posiciones en elformat()
método, pero el cambio de posiciones siempre fue al menos 0.01 más lento que el método de formato normal.Muestra de resultados de la prueba:
Los ejecuté porque utilizo la concatenación de cadenas en mis scripts, y me preguntaba cuál era el costo. Los ejecuté en diferentes órdenes para asegurarme de que nada interfiriera, o que obtuviera un mejor rendimiento siendo el primero o el último. En una nota al margen, agregué algunos generadores de cadenas más largas en esas funciones como
"%s" + ("a" * 1024)
y el concat regular fue casi 3 veces más rápido (1.1 vs 2.8) que usar los métodosformat
y%
. Supongo que depende de las cadenas y de lo que intentas lograr. Si el rendimiento realmente importa, sería mejor probar cosas diferentes y probarlas. Tiendo a elegir la legibilidad sobre la velocidad, a menos que la velocidad se convierta en un problema, pero soy solo yo. Así que no me gustó mi copiar / pegar, tuve que poner 8 espacios en todo para que se vea bien. Yo suelo usar 4.fuente
str.format()
ystr.join()
sobre la concatenación normal. También estoy atento a las 'f-strings' de PEP 498 , que ha sido aceptada recientemente. En cuanto a lasstr()
llamadas que afectan el rendimiento, estoy seguro de que tiene razón. No tenía idea de lo caras que eran las llamadas a funciones en ese momento. Sigo pensando que las pruebas deben hacerse cuando haya alguna duda.join_(): return ''.join(["test ", str(1), ", with number ", str(2)])
, parecejoin
que también es más lento que el porcentaje.Recuerde, las decisiones estilísticas son prácticas, si alguna vez planea mantener o depurar su código :-) Hay una cita famosa de Knuth (¿posiblemente citando a Hoare?): "Deberíamos olvidarnos de las pequeñas eficiencias, digamos aproximadamente el 97% del tiempo: La optimización temprana es la raíz de todo mal."
Siempre que tenga cuidado de no (decir) convertir una tarea O (n) en una tarea O (n 2 ), elegiría la que le resulte más fácil de entender.
fuente
Utilizo la sustitución siempre que puedo. Solo uso la concatenación si estoy construyendo una cadena en, digamos, un bucle for.
fuente
En realidad, lo correcto, en este caso (construir caminos) es usar
os.path.join
. Sin concatenación o interpolación de cadenasfuente