¿Cómo usar la nueva línea '\ n' en f-string para formatear la salida en Python 3.6?

109

Me gustaría saber cómo formatear este caso de manera Pythonic con f-strings:

names = ['Adam', 'Bob', 'Cyril']
text = f"Winners are:\n{'\n'.join(names)}"
print(text)

El problema es que '\'no se puede usar dentro de las {...}porciones de expresión de una cadena f. Rendimiento esperado:

Winners are:
Adam
Bob
Cyril
malmed
fuente
10
f"Winners are:\n{chr(10).join(names)}"
wim

Respuestas:

123

No puedes. Las barras invertidas no pueden aparecer dentro de las llaves {}; hacerlo da como resultado SyntaxError:

>>> f'{\}'
SyntaxError: f-string expression part cannot include a backslash

Esto se especifica en el PEP para f-strings:

Es posible que no aparezcan barras invertidas dentro de las porciones de expresión de las cadenas de f, [...]

Una opción es asignar '\n'un nombre y luego .joinen el interior de f-string; es decir, sin usar un literal:

names = ['Adam', 'Bob', 'Cyril']
nl = '\n'
text = f"Winners are:{nl}{nl.join(names)}"
print(text)

Resultados en:

Winners are:
Adam
Bob
Cyril

Otra opción, según lo especificado por @wim, es usar chr(10)para ser \ndevuelto y luego unirse allí.f"Winners are:\n{chr(10).join(names)}"

Otro, por supuesto, es de '\n'.joinantemano y luego agregar el nombre en consecuencia:

n = "\n".join(names)
text = f"Winners are:\n{n}"

lo que da como resultado la misma salida.

Nota:

Esta es una de las pequeñas diferencias entre f-strings y str.format. En este último, siempre puede usar la puntuación siempre que se descomprima un dictado loco correspondiente que contenga esas claves:

>>> "{\\} {*}".format(**{"\\": 'Hello', "*": 'World!'})
"Hello World!"

(Por favor, no hagas esto).

En el primero, la puntuación no está permitida porque no puede tener identificadores que los usen.


Aparte: definitivamente optaría por printo format, como sugieren las otras respuestas, como alternativa. Las opciones que he dado solo se aplican si, por alguna razón, debe usar cadenas de f.

El hecho de que algo sea nuevo no significa que debas intentar hacer todo con él ;-)

Dimitris Fasarakis Hilliard
fuente
55

No necesita f-strings u otros formateadores para imprimir una lista de cadenas con un separador. Simplemente use el separgumento de palabra clave para print():

names = ['Adam', 'Bob', 'Cyril']
print('Winners are:', *names, sep='\n')

Salida:

Winners are:
Adam
Bob
Cyril

Dicho esto, podría decirse que usar str.join()/str.format() aquí sería más simple y más legible que cualquier solución alternativa de f-string:

print('\n'.join(['Winners are:', *names]))
print('Winners are:\n{}'.format('\n'.join(names)))
Eugene Yarmash
fuente
13
La mejor respuesta hasta ahora. Utilizo el desempaquetado de estrellas en la función de impresión todo el tiempo estos días para ver el interior de algún objeto, por ejemplo, print(*dir(some_object), sep='\n')o print(*vars(some_object), sep='\n').
Rick apoya a Monica el
1
¿Qué hace si no desea imprimir la lista directamente, por ejemplo, si la está pasando a un registrador?
bob
1
@bob: sólo tiene que utilizar str.join(): text = '\n'.join(['Winners are:', *names]). Por cierto, print()se puede usar para escribir en cualquier archivo (especificado con el fileargumento,sys.stdout por defecto).
Eugene Yarmash
10

No puede usar barras invertidas en f-strings como han dicho otros, pero podría evitar esto usando os.linesep(aunque tenga en cuenta que esto no estará \nen todas las plataformas y no se recomienda a menos que lea / escriba archivos binarios; vea los comentarios de Rick ):

>>> import os
>>> names = ['Adam', 'Bob', 'Cyril']
>>> print(f"Winners are:\n{os.linesep.join(names)}")
Winners are:
Adam
Bob
Cyril 

O quizás de una manera menos legible, pero garantizada \n, con chr():

>>> print(f"Winners are:\n{chr(10).join(names)}")
Winners are:
Adam
Bob
Cyril
Chris_Rands
fuente
2
No era yo, pero usarlo noos.linesep es una buena idea al escribir texto.
Rick apoya a Monica el
1
@RickTeachey Ya agregué la advertencia entre paréntesis y sugiero un enfoque alternativo. De todos modos, el OP está imprimiendo en la pantalla, no escribiendo en un archivo abierto en modo texto
Chris_Rands
No creo que importe. os.linesepes solo para leer, o leer y escribir en modo binario . Sé que funcionará igual en este caso, pero es un mal hábito comenzar. Pero de nuevo: yo no fui el voto negativo. La advertencia es suficiente para mí. :)
Rick apoya a Monica el
6

Las otras respuestas dan ideas sobre cómo poner el carácter de nueva línea en un campo de cadena f. Sin embargo, yo diría que para el ejemplo que dio el OP (que puede o no ser indicativo del caso de uso real del OP), ninguna de estas ideas debería usarse realmente.

El objetivo de usar f-strings es aumentar la legibilidad del código. No hay nada que puedas hacer con f-strings que no puedas hacer format. Considere cuidadosamente si hay algo más legible sobre esto (si pudiera hacerlo):

f"Winners are:\n{'\n'.join(names)}"

...o esto:

newline = '\n'
f"Winners are:\n{newline.join(names)}"

...o esto:

"Winners are:\n{chr(10).join(names)}"

vs. esto:

"Winners are:\n{}".format('\n'.join(names))

La última forma es al menos igual de legible, si no más.

En resumen: no use un martillo cuando necesite un destornillador solo porque tiene uno nuevo y brillante. El código se lee con mucha más frecuencia de lo que se escribe.

Para otros casos de uso, sí, es posible que la chr(10)idea o la newlineidea sea apropiada. Pero no por el dado.

Rick apoya a Monica
fuente
7
La legibilidad es subjetiva :) ... la práctica antigua se adapta a los expertos y puede ser más legible en algunos casos, pero puede ser casi desconocida para los novatos y, por lo tanto, ilegible para ellos. Perdón por el punto de vista filosófico.
malmed
2
@malmed La legibilidad generalmente no es subjetiva. Definitivamente no en este caso. Pero no vale la pena discutirlo mucho.
Rick apoya a Monica
@malmed Tienes razón en que la legibilidad es "subjetiva" en el sentido de que se puede entrenar por experiencia previa. Pero debido a que nuestros cerebros y sentidos tienen limitaciones, la legibilidad se puede medir objetivamente en términos de qué tan fácil es físicamente escanear el texto relevante, con qué frecuencia los cerebros humanos tienden a hacer coincidir los patrones correctamente, qué tan correctamente insinúa a nuestro cerebro las predicciones sobre otros. código (incluido el comienzo de una declaración / línea que insinúe cuál será el final), y con qué facilidad se vuelve más legible para un principiante.
mtraceur