Formatação de string em Python 3

114

Eu faço isso no Python 2:

"(%d goals, $%d)" % (self.goals, self.penalties)

Qual é a versão Python 3 disso?

Tentei pesquisar exemplos online, mas continuei obtendo versões do Python 2.

JoseBazBaz
fonte
Não foi descontinuado; seu código funciona bem. Leia mais aqui .
jackcogdill
32
Nota para o leitor casual: o cifrão não tem nenhum significado especial. É apenas um cifrão aqui. (Obrigado Martijn Pieters)
kevinarpe
1
pyformat.info e python-course.eu/python3_formatted_output.php (Não são meus sites)
Christophe Roussy
1
O cifrão tornou isso muito confuso.
cchamberlain

Respostas:

173

Aqui estão os documentos sobre a sintaxe do "novo" formato. Um exemplo seria:

"({:d} goals, ${:d})".format(self.goals, self.penalties)

Se goalse penaltiesforem inteiros (ou seja, seu formato padrão é ok), pode ser reduzido para:

"({} goals, ${})".format(self.goals, self.penalties)

E como os parâmetros são campos de self, também há uma maneira de fazer isso usando um único argumento duas vezes (como @Burhan Khalid observou nos comentários):

"({0.goals} goals, ${0.penalties})".format(self)

Explicando:

  • {} significa apenas o próximo argumento posicional, com formato padrão;
  • {0}significa o argumento com índice 0, com formato padrão;
  • {:d} é o próximo argumento posicional, com formato de inteiro decimal;
  • {0:d}é o argumento com índice 0, com formato decimal inteiro.

Existem muitas outras coisas que você pode fazer ao selecionar um argumento (usando argumentos nomeados em vez de posicionais, acessando campos, etc) e muitas opções de formato também (preencher o número, usar separadores de milhares, mostrar o sinal ou não, etc). Alguns outros exemplos:

"({goals} goals, ${penalties})".format(goals=2, penalties=4)
"({goals} goals, ${penalties})".format(**self.__dict__)

"first goal: {0.goal_list[0]}".format(self)
"second goal: {.goal_list[1]}".format(self)

"conversion rate: {:.2f}".format(self.goals / self.shots) # '0.20'
"conversion rate: {:.2%}".format(self.goals / self.shots) # '20.45%'
"conversion rate: {:.0%}".format(self.goals / self.shots) # '20%'

"self: {!s}".format(self) # 'Player: Bob'
"self: {!r}".format(self) # '<__main__.Player instance at 0x00BF7260>'

"games: {:>3}".format(player1.games)  # 'games: 123'
"games: {:>3}".format(player2.games)  # 'games:   4'
"games: {:0>3}".format(player2.games) # 'games: 004'

Observação: como outros apontaram, o novo formato não substitui o anterior, ambos estão disponíveis no Python 3 e nas versões mais recentes do Python 2 também. Alguns podem dizer que é uma questão de preferência, mas IMHO, o mais novo é muito mais expressivo do que o mais antigo e deve ser usado sempre que escrever um novo código (a menos que seja voltado para ambientes mais antigos, é claro).

mgibsonbr
fonte
9
Você também pode fazer"({0.goals} goals, ${0.penalties})".format(self)
Burhan Khalid
Você precisa tirar '%' fora das chaves, por exemplo, {: .2f%} -> {: .2f}%
SuperElectric
@SuperElectric você quer dizer, nesta linha "conversion rate: {:.2%}".format(self.goals / self.shots):? Funciona bem para mim como está ... (Python 3.4) Observe que não há fnele, estou pedindo para formatar como uma porcentagem, não como um número de ponto flutuante.
mgibsonbr
Você está certo; parece funcionar no Python 3.4, então tudo bem, já que o OP estava perguntando sobre o Python3. Acabei de descobrir que não funcionava com o python 2.7.6. "{:.2f}%".format(float_num)funciona bem para ambos.
SuperElectric
1
@JohnSchmitt Sim, este exemplo deveria fornecer a mesma saída exata que o código fornecido na pergunta. O $não tem nenhum significado especial aqui, nem na sintaxe do formato antigo nem no novo, portanto, deve estar presente na string gerada, inalterada.
mgibsonbr
67

Python 3.6 agora suporta interpolação de string literal abreviada com PEP 498 . Para o seu caso de uso, a nova sintaxe é simplesmente:

f"({self.goals} goals, ${self.penalties})"

Isso é semelhante ao .formatpadrão anterior , mas permite fazer coisas facilmente como :

>>> width = 10
>>> precision = 4
>>> value = decimal.Decimal('12.34567')
>>> f'result: {value:{width}.{precision}}'
'result:      12.35'
JDong
fonte
12

Essa linha funciona como está no Python 3.

>>> sys.version
'3.2 (r32:88445, Oct 20 2012, 14:09:29) \n[GCC 4.5.2]'
>>> "(%d goals, $%d)" % (self.goals, self.penalties)
'(1 goals, $2)'
Mark Reed
fonte
ESTÁ BEM. LEGAL. Depois de postar a pergunta, continuei minha pesquisa e descobri que temos que fazer {% d} em vez de apenas% d, também está correto? Ou é a maneira Python2 a única maneira de fazer isso?
JoseBazBaz
2
Python 3 apresenta uma nova sintaxe - que são as chaves - mas você não é obrigado a usá-la. Você pode usar o antigo ou o novo. Mas eles são diferentes; se você estiver usando curvas, não use sinais de porcentagem.
Mark Reed
2

Eu gosto dessa abordagem

my_hash = {}
my_hash["goals"] = 3 #to show number
my_hash["penalties"] = "5" #to show string
print("I scored %(goals)d goals and took %(penalties)s penalties" % my_hash)

Observe os d e s anexados aos colchetes, respectivamente.

a saída será:

I scored 3 goals and took 5 penalties
fullstacklife
fonte