Como usar nova linha '\ n' em f-string para formatar a saída em Python 3.6?

109

Eu gostaria de saber como formatar este caso de uma forma pitônica com f-strings:

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

O problema é que '\'não pode ser usado dentro das {...}partes da expressão de uma string f. Saída esperada:

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

Respostas:

123

Você não pode. Barras invertidas não podem aparecer dentro das chaves {}; fazer isso resulta em SyntaxError:

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

Isso é especificado no PEP para f-strings:

As barras invertidas podem não aparecer dentro das partes da expressão das strings f, [...]

Uma opção é atribuir '\n'a um nome e depois .joindentro da f-string; ou seja, sem usar um literal:

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

Resulta em:

Winners are:
Adam
Bob
Cyril

Outra opção, conforme especificado por @wim, é usar chr(10)para obter o \nretorno e, em seguida, ingressar nele.f"Winners are:\n{chr(10).join(names)}"

Outra, é claro, é '\n'.joinantes e depois adicionar o nome de acordo:

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

que resulta na mesma saída.

Nota:

Esta é uma das pequenas diferenças entre f-strings e str.format. No último, você sempre pode usar pontuação concedida que um ditado maluco correspondente é descompactado que contém essas chaves:

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

(Por favor, não faça isso.)

No primeiro caso, a pontuação não é permitida porque você não pode ter identificadores que os utilizem.


À parte: eu definitivamente optaria por printou format, como as outras respostas sugerem como alternativa. As opções que dei se aplicam apenas se você precisar, por algum motivo, usar strings f.

Só porque algo é novo, não significa que você deva tentar fazer tudo com ele ;-)

Dimitris Fasarakis Hilliard
fonte
55

Você não precisa de f-strings ou outros formatadores para imprimir uma lista de strings com um separador. Basta usar o separgumento de palavra - chave para print():

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

Resultado:

Winners are:
Adam
Bob
Cyril

Dito isso, usar str.join()/str.format() here seria, sem dúvida, mais simples e mais legível do que qualquer solução alternativa de string f:

print('\n'.join(['Winners are:', *names]))
print('Winners are:\n{}'.format('\n'.join(names)))
Eugene Yarmash
fonte
13
Melhor resposta até agora. Eu uso o desempacotamento com estrela na função de impressão o tempo todo hoje em dia para dar uma olhada dentro de algum objeto, por exemplo, print(*dir(some_object), sep='\n')ou print(*vars(some_object), sep='\n').
Rick apoia Monica de
1
O que você faz se não quiser imprimir a lista diretamente, por exemplo, se estiver passando para um logger?
bob
1
@bob: então é só usar str.join(): text = '\n'.join(['Winners are:', *names]). BTW, print()pode ser usado para gravar em qualquer arquivo (especificado com o fileargumento, sys.stdoutpor padrão).
Eugene Yarmash
10

Você não pode usar barras invertidas em strings f como outros disseram, mas você pode contornar isso usando os.linesep(embora observe que isso não será \nem todas as plataformas e não é recomendado a menos que leia / grave arquivos binários; veja os comentários de Rick ):

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

Ou talvez de uma forma menos legível, mas garantidamente \n, com chr():

>>> print(f"Winners are:\n{chr(10).join(names)}")
Winners are:
Adam
Bob
Cyril
Chris_Rands
fonte
2
Não fui eu, mas usar nãoos.linesep é uma boa ideia ao escrever um texto.
Rick apoia Monica em
1
@RickTeachey Eu já adicionei a advertência entre parênteses e sugeri uma abordagem alternativa. De qualquer forma, o OP está imprimindo na tela, não gravando em um arquivo aberto em modo de texto
Chris_Rands
Eu não acho que isso importe. os.linesepserve apenas para leitura ou leitura e escrita em modo binário . Sei que funcionará da mesma forma neste caso, mas é um mau hábito começar. Mas, novamente: eu não fui o downvote. A advertência é boa o suficiente para mim. :)
Rick apoia Monica de
6

As outras respostas fornecem ideias sobre como colocar o caractere de nova linha em um campo de string f. No entanto, eu argumentaria que, para o exemplo dado pelo OP (que pode ou não ser indicativo do caso de uso real do OP), nenhuma dessas idéias deve ser realmente usada.

O objetivo de usar strings f é aumentar a legibilidade do código. Não há nada que você possa fazer com as cordas F que você não possa fazer format. Considere cuidadosamente se há algo mais legível sobre isso (se você pudesse fazer isso):

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

...ou isto:

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

...ou isto:

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

vs. isto:

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

A última forma é pelo menos tão legível, se não mais.

Resumindo: não use um martelo quando precisar de uma chave de fenda só porque você tem uma nova brilhante. O código é lido com muito mais frequência do que escrito.

Para outros casos de uso, sim, é possível que a chr(10)ideia ou newlineideia seja apropriada. Mas não para aquele dado.

Rick apóia a monica
fonte
7
A legibilidade é subjetiva :) ... a prática antiga serve para os experientes e pode ser mais legível em alguns casos, mas pode ser quase desconhecida para os novatos e, portanto, ilegível para eles. Desculpe pelo ponto de vista filosófico.
malmed em
2
@malmed A legibilidade geralmente não é subjetiva. Definitivamente não neste caso. Mas não vale a pena discutir sobre isso.
Rick apoia Monica em
@malmed Você está certo ao dizer que a legibilidade é "subjetiva" no sentido de que pode ser treinada por experiência anterior. Mas, como nossos cérebros e sentidos têm limitações, a legibilidade pode ser medida objetivamente em termos de quão fisicamente fácil é escanear o texto relevante, com que frequência os cérebros humanos tendem a combiná-lo corretamente, quão corretamente ele sugere as previsões do nosso cérebro sobre outros código (incluindo o início de uma instrução / linha sugerindo qual será o final) e com que rapidez se torna mais legível para um novato.
mtraceur