Formato de cadenas vs concatenación

Veo a mucha gente usando cadenas de formato como esta:

root = "sample" output = "output" path = "{}/{}".format(root, output) 

En lugar de simplemente concatenar cadenas como esta:

 path = root + '/' + output 

¿Las cadenas de formato tienen mejor rendimiento o es solo para apariencia?

Es solo por el aspecto. Puedes ver de un vistazo cuál es el formato. A muchos de nosotros nos gusta la legibilidad mejor que la microoptimización.

Veamos lo que dice %timeit IPython:

 Python 3.7.2 (default, Jan 3 2019, 02:55:40) IPython 5.8.0 Intel(R) Core(TM) i5-4590T CPU @ 2.00GHz In [1]: %timeit root = "sample"; output = "output"; path = "{}/{}".format(root, output) The slowest run took 12.44 times longer than the fastest. This could mean that an intermediate result is being cached. 1000000 loops, best of 5: 223 ns per loop In [2]: %timeit root = "sample"; output = "output"; path = root + '/' + output The slowest run took 13.82 times longer than the fastest. This could mean that an intermediate result is being cached. 10000000 loops, best of 5: 101 ns per loop In [3]: %timeit root = "sample"; output = "output"; path = "%s/%s" % (root, output) The slowest run took 27.97 times longer than the fastest. This could mean that an intermediate result is being cached. 10000000 loops, best of 5: 155 ns per loop In [4]: %timeit root = "sample"; output = "output"; path = f"{root}/{output}" The slowest run took 19.52 times longer than the fastest. This could mean that an intermediate result is being cached. 10000000 loops, best of 5: 77.8 ns per loop 

Como con la mayoría de las cosas, habrá una diferencia de rendimiento, pero pregúntate a ti mismo “¿Realmente importa si esto es ns más rápido?”. El método de root + '/' output es rápido y fácil de escribir. Pero esto puede ser difícil de leer realmente rápido cuando tiene varias variables para imprimir

 foo = "X = " + myX + " | Y = " + someY + " Z = " + Z.toString() 

vs

 foo = "X = {} | Y= {} | Z = {}".format(myX, someY, Z.toString()) 

¿Qué es más fácil de entender qué está pasando? A menos que realmente necesite mejorar el rendimiento, elija la forma en que sea más fácil de leer y comprender para las personas

No es solo para “looks”, o para poderosas conversiones de tipos léxicos; También es imprescindible para la internacionalización.

Puede intercambiar la cadena de formato en función del idioma seleccionado.

Con una larga línea de concatenaciones de cadenas incorporadas en el código fuente, esto resulta efectivamente imposible de realizar correctamente.

El formato de cadena está libre de tipos de datos mientras se vinculan Mientras que en la concatenación tenemos que escribir cast o convertir los datos en consecuencia.

Por ejemplo:

 a = 10 b = "foo" c = str(a) + " " + b print c > 10 foo 

Se podría hacer vía formato de cadena como:

 a = 10 b = "foo" c = "{} {}".format(a, b) print c > 10 foo 

De tal manera que dentro de los marcadores de posición {} {} , asumimos que dos cosas van más allá, es decir, en este caso, son a y b .

Estoy de acuerdo en que el formato se utiliza principalmente para facilitar la lectura, pero desde el lanzamiento de f-strings en 3.6, las tablas se han convertido en términos de rendimiento. También opino que las cadenas F son más legibles / mantenibles ya que 1) se pueden leer de izquierda a derecha como el texto más común y 2) se evitan las desventajas relacionadas con el espaciado de la concatenación ya que las variables están dentro de la cadena.

Ejecutando este código:

 from timeit import timeit runs = 1000000 def print_results(time, start_string): print(f'{start_string}\n' f'Total: {time:.4f}s\n' f'Avg: {(time/runs)*1000000000:.4f}ns\n') t1 = timeit('"%s, %s" % (greeting, loc)', setup='greeting="hello";loc="world"', number=runs) t2 = timeit('f"{greeting}, {loc}"', setup='greeting="hello";loc="world"', number=runs) t3 = timeit('greeting + ", " + loc', setup='greeting="hello";loc="world"', number=runs) t4 = timeit('"{}, {}".format(greeting, loc)', setup='greeting="hello";loc="world"', number=runs) print_results(t1, '% replacement') print_results(t2, 'f strings') print_results(t3, 'concatenation') print_results(t4, '.format method') 

produce este resultado en mi máquina:

 % replacement Total: 0.3044s Avg: 304.3638ns f strings Total: 0.0991s Avg: 99.0777ns concatenation Total: 0.1252s Avg: 125.2442ns .format method Total: 0.3483s Avg: 348.2690ns 

Una respuesta similar a una pregunta diferente se da en esta respuesta .

A partir de Python 3.6, puedes hacer una interpolación de cadena literal al insertar f en la cadena:

 root = "sample" output = "output" path = f"{root}/{output}" 

Es para las miradas y el mantenimiento del código. Es realmente más fácil editar tu código si usaste el formato. También cuando usas + puedes perderte los detalles como espacios. Utilice el formato para su bien y posibles mantenedores.