Usando vários argumentos para formatação de string em Python (por exemplo, '% s…% s')

174

Eu tenho uma string que se parece '%s in %s'e quero saber como separar os argumentos para que sejam dois% s diferentes. Minha mente vinda de Java surgiu com isso:

'%s in %s' % unicode(self.author),  unicode(self.publication)

Mas isso não funciona, então como fica em Python?

reitor
fonte

Respostas:

191

A resposta de Mark Cidade está certa - você precisa fornecer uma tupla.

No entanto, a partir do Python 2.6, você pode usar em formatvez de %:

'{0} in {1}'.format(unicode(self.author,'utf-8'),  unicode(self.publication,'utf-8'))

O uso de %para formatação de seqüências de caracteres não é mais incentivado.

Esse método de formatação de string é o novo padrão no Python 3.0 e deve ser preferido à% de formatação descrita em Operações de formatação de string no novo código.

Mark Byers
fonte
5
Também começando com o Python 2.7, ele pode soltar o número do índice, ou seja, usar uma '{} in {}'string de formato simples .
Cristian Ciupitu
121

Se você estiver usando mais de um argumento, ele deverá estar em uma tupla (observe os parênteses extras):

'%s in %s' % (unicode(self.author),  unicode(self.publication))

Como a EOL aponta, a unicode()função geralmente assume a codificação ASCII como padrão; portanto, se você tiver caracteres não ASCII, é mais seguro transmitir explicitamente a codificação:

'%s in %s' % (unicode(self.author,'utf-8'),  unicode(self.publication('utf-8')))

E a partir do Python 3.0, é preferível usar a str.format()sintaxe:

'{0} in {1}'.format(unicode(self.author,'utf-8'),unicode(self.publication,'utf-8'))
Mark Cidade
fonte
60

Em um objeto de tupla / mapeamento para vários argumentos format

A seguir, trecho da documentação:

Dado format % values, %as especificações de conversão em formatsão substituídas por zero ou mais elementos de values. O efeito é semelhante ao uso sprintf()na linguagem C.

Se formatrequer um único argumento, os valores podem ser um único objeto sem tupla. Caso contrário, os valores devem ser um tuplo com exactamente o número de itens especificados pela formatcadeia , ou um único objecto de mapeamento (por exemplo, um dicionário).

Referências


Em str.formatvez de%

Uma alternativa mais nova ao %operador é usar str.format. Aqui está um trecho da documentação:

str.format(*args, **kwargs)

Execute uma operação de formatação de string. A cadeia na qual esse método é chamado pode conter texto literal ou campos de substituição delimitados por chaves {}. Cada campo de substituição contém o índice numérico de um argumento posicional ou o nome de um argumento de palavra-chave. Retorna uma cópia da sequência em que cada campo de substituição é substituído pelo valor da sequência do argumento correspondente.

Este método é o novo padrão no Python 3.0 e deve ser preferido à %formatação .

Referências


Exemplos

Aqui estão alguns exemplos de uso:

>>> '%s for %s' % ("tit", "tat")
tit for tat

>>> '{} and {}'.format("chicken", "waffles")
chicken and waffles

>>> '%(last)s, %(first)s %(last)s' % {'first': "James", 'last': "Bond"}
Bond, James Bond

>>> '{last}, {first} {last}'.format(first="James", last="Bond")
Bond, James Bond

Veja também

poligenelubricants
fonte
Não tenho como testar isso (não conheço muito o Python), mas os exemplos parecem sugerir que algo como '{self.author} in {self.publication}'.format(self=self)deveria "funcionar". Só não tenho certeza sobre a unicodecoisa toda .
polygenelubricants
1
Sim, você pode realmente acessar atributos (e também índices). Consulte docs.python.org/library/string.html#formatstrings Portanto, no seu exemplo, você poderia ter usado {first[0]}para obter a inicial J.
Duncan
10

Você deve apenas colocar os valores entre parênteses:

'%s in %s' % (unicode(self.author),  unicode(self.publication))

Aqui, pela primeira vez, %so unicode(self.author)será colocado. E para o segundo %s, o unicode(self.publication)será usado.

Nota: Você deve favorecer string formattinga %Notação. Mais informações aqui

Bahadir Tasdemir
fonte
Eu não posso acreditar que as pessoas ainda sugerem %sem vezformat
user1767754
8

Há um problema significativo com algumas das respostas postadas até agora: unicode()decodifica a codificação padrão, que geralmente é ASCII; de fato, unicode()tenta "dar sentido" aos bytes dados, convertendo-os em caracteres. Portanto, o código a seguir, que é essencialmente o recomendado pelas respostas anteriores, falha na minha máquina:

# -*- coding: utf-8 -*-
author = 'éric'
print '{0}'.format(unicode(author))

dá:

Traceback (most recent call last):
  File "test.py", line 3, in <module>
    print '{0}'.format(unicode(author))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

A falha vem do fato de authornão conter apenas bytes ASCII (ou seja, com valores em [0; 127]) e unicode()decodificar a partir de ASCII por padrão (em muitas máquinas).

Uma solução robusta é fornecer explicitamente a codificação usada em seus campos; tomando UTF-8 como exemplo:

u'{0} in {1}'.format(unicode(self.author, 'utf-8'), unicode(self.publication, 'utf-8'))

(ou sem a inicial u, dependendo se você deseja um resultado Unicode ou uma sequência de bytes).

Nesse ponto, convém considerar que os campos authore publicationsejam cadeias Unicode, em vez de decodificá-las durante a formatação.

Eric O Lebigot
fonte
5

Para python2, você também pode fazer isso

'%(author)s in %(publication)s'%{'author':unicode(self.author),
                                  'publication':unicode(self.publication)}

o que é útil se você tiver muitos argumentos para substituir (principalmente se estiver fazendo internacionalização)

Suporta Python2.6 em diante .format()

'{author} in {publication}'.format(author=self.author,
                                   publication=self.publication)
John La Rooy
fonte
4

Você também pode usá-lo limpo e simples (mas errado! Porque você deve usar formatcomo Mark Byers disse) fazendo:

print 'This is my %s formatted with %d arguments' % ('string', 2)
Lordn__n
fonte
3

Para completar, no python, 3,6-f-string são introduzidos no PEP-498 . Essas cadeias tornam possível

incorpore expressões dentro de literais de string, usando uma sintaxe mínima.

Isso significaria que, no seu exemplo, você também poderia usar:

f'{self.author} in {self.publication}'
westr
fonte