Por que% s é melhor que + para concatenação?

88

Eu entendo que devemos usar %spara concatenar uma string em vez de +em Python.

Eu poderia fazer qualquer um dos seguintes:

hello = "hello"
world = "world"

print hello + " " + world
print "%s %s" % (hello, world)
print "{} {}".format(hello, world)
print ' '.join([hello, world])

Mas por que devo usar outra coisa senão a +? É mais rápido escrever concatenação com um simples +. Então, se você observar a sequência de formatação, especifique os tipos, por exemplo, %se assim por diante %d. Entendo que seria melhor ser explícito sobre o tipo.

Mas então li que o uso +para concatenação deve ser evitado, mesmo que seja mais fácil digitar. Existe uma razão clara para que as seqüências de caracteres devam ser concatenadas de uma dessas outras maneiras?

Niklas Rosencrantz
fonte
29
Quem te disse que é melhor?
precisa saber é
3
%snão é para concatenação, é uma especificação de conversão para formatação de string derivada de C's printf(3). Existem casos para usar esse ou um operador de concatenação; que você usa deve basear-se no julgamento da situação, não no dogma. O quão fácil é escrever o código é totalmente irrelevante, porque você fará isso apenas uma vez.
Blrfl
Eu recentrar a questão para apenas python (embora eu não sou uma pessoa python e ainda pode haver falhas no código). Verifique se esta é a pergunta que você está fazendo, faça as atualizações apropriadas e considere fazer uma pergunta diferente se estiver interessado em C ou Java.
12
E agora temos as cordas f superiores ! print(f"{hello} {world}"), tem legibilidade de concatenação, pois as variáveis ​​são vistas onde ocorrem na cadeia e são mais rápidas que str.format.
Enrico Borba

Respostas:

88
  1. Legibilidade. A sintaxe da string de formato é mais legível, pois separa o estilo dos dados. Além disso, no Python, a %ssintaxe coagirá automaticamente qualquer strtipo não str; enquanto a concatenação funciona apenas com str, e você não pode concatenar strcom int.

  2. Atuação. No Python stré imutável, portanto, a string esquerda e direita devem ser copiadas para a nova string para cada par de concatenação. Se você concatenar quatro cadeias de comprimento 10, estará copiando (10 + 10) + ((10 + 10) +10) + (((10 + 10) +10) +10) = 90 caracteres, em vez de apenas 40 personagens. E as coisas pioram quadraticamente à medida que o número e o tamanho da corda aumentam. O Java otimiza esse caso algumas vezes, transformando a série de concatenação em uso StringBuilder, mas o CPython não.

  3. Para alguns casos de uso, a biblioteca de log fornece uma API que usa a sequência de formato para criar a sequência de entrada de log lazily ( logging.info("blah: %s", 4)). Isso é ótimo para melhorar o desempenho se a biblioteca de logs decidir que a entrada de log atual será descartada por um filtro de log, portanto, não é necessário formatar a string.

Lie Ryan
fonte
31
você tem alguma fonte científica ou empírica para o número 1? Porque eu acho que é muito muito menos legível (especialmente com mais de 2 ou três argumentos)
Lovis
4
@ L.Möller: Não sei ao certo que tipo de fonte você espera do que é, em última análise, uma experiência subjetiva (facilidade de leitura), mas se você quer meu raciocínio: 1)% s requer 2 caracteres extras por espaço reservado vs + requer mínimo de 4 (ou 8 se você seguir PEP8, 13 se forçar), 2)% s é incluído em uma única sequência, portanto é mais fácil analisar visualmente, com +, você tem mais partes móveis: sequência próxima, operador, variável , operator, open string, 3) coloração de sintaxe% s tem uma cor para cada função: string e espaço reservado, com + você obtém três cores: string, operador e coloração variável.
Lie Ryan
4
@ L.Möller: 4) Eu tenho a opção de colocar seqüências de caracteres de formato mais longas em uma variável ou dicionário, longe de onde a formatação precisa ser feita; 5) a string de formato pode ser especificada pelo usuário em um arquivo de configuração, comando args ou banco de dados , o mesmo não pode ser dito com concatenações. Mas sim, eu também não usaria% s quando tenho mais de 4-5 coisas para interpolar, em vez disso usaria a variante% (varname) s ou "{foo}". Format () no Python. Eu acho que os nomes explícitos melhoram a legibilidade para seqüências de formato mais longas, com muitas variáveis ​​interpoladas.
Lie Ryan
2
Não sei o que é "verdade", é por isso que pergunto se você tem provas :-). Realmente concordo com o seu segundo comentário
Lovis
6
Acho que o nº 2 é suspeito - você tem provas documentadas? Não estou extremamente familiarizado com Java, mas a concatenação em C # é mais rápida que a interpolação de cadeias . Eu concordo completamente com o nº 1 e realmente confio nisso para decidir quando usar quais, mas você precisa se lembrar de que a interpolação requer uma quantidade de análise e complexidade de seqüências de caracteres em que a concatenação não exige nada disso.
Jimmy Hoffa
48

Eu sou o único que lê da esquerda para a direita?

Para mim, usar %sé como ouvir falantes de alemão, onde tenho que esperar até o final de uma frase muito longa para ouvir o que é o verbo.

Qual destes é mais claro à primeira vista?

"your %s is in the %s" % (object, location)

ou

"your " + object + " is in the " + location  
Mawg
fonte
17
Obviamente, isso é subjetivo, pois acho o primeiro mais legível - e mais fácil de escrever e editar. O segundo mistura o texto com o código que obscurece os dois e adiciona ruído. Por exemplo, é fácil errar os espaços no segundo.
JacquesB
5
@ JacquesB Na verdade, acho que seu cérebro está tão familiarizado com esse formato que você pula imediatamente para os parênteses e substitui as palavras instantaneamente. Tecnicamente, não é uma leitura da esquerda para a direita, mas está perfeitamente bem. Acho que faço isso também, então sim, é mais fácil ler porque sei que tenho que lidar com problemas estúpidos de espaçamento antes e depois das citações no segundo, e é muito lento trabalhar com isso.
Nelson Nelson
3
Depois de ndécadas, minha mente funciona assim também ;-) Mas ainda mantenho minha resposta, a segunda é mais clara e fácil de ler, portanto, de manter. E isso se torna mais aparente quanto mais parâmetros você tiver. No final, se for um show de um homem, vá com o que você está familiarizado e confortável; se for um esforço de equipe, imponha análises de consistência e código; as pessoas podem se acostumar com qualquer um.
Mawg 29/09/16
4
O primeiro é muito mais legível para mim, porque tem menos "cruft" no meio da frase. É mais fácil para os meus olhos olharem para o final do que para o meu cérebro analisar as aspas, espaços e vantagens extras. Claro, agora eu prefiro muito mais Python seqüências de formato 3.6: f"your {object} is in the {location}".
Dustin Wyatt
8
Também acho ainda mais difícil ler e escrever quando a variável precisa ser cercada por aspas. "your '" + object + "' is in the '" + location + "'"... Eu nem tenho certeza se eu tenho esse direito agora ...
Dustin Wyatt
12

Um exemplo que esclarece o argumento de legibilidade:

print 'id: ' + id + '; function: ' + function + '; method: ' + method + '; class: ' + class + ' -- total == ' + total

print 'id: %s; function: %s; method: %s; class: %s --total == %s' % \
   (id, function, method, class, total)

(Observe que o segundo exemplo não é apenas mais legível, mas também mais fácil de editar, você pode alterar o modelo em uma linha e a lista de variáveis ​​na outra)

Um problema separado é que o código% s também se converte na string, caso contrário, é necessário usar a chamada str () que também é menos legível do que o código% s.

Chuvoso
fonte
1
Não concordo com a sua primeira declaração, mas podemos concordar em discordar, eu estava prestes a postar uma resposta ao longo das linhas do seu segundo, para upvote
MAWG
6

O uso não+ deve ser evitado em geral. Em muitos casos, é a abordagem correta. Usar ou são preferíveis apenas em casos específicos, e geralmente é bastante óbvio quando eles são a melhor solução.%s.join()

No seu exemplo, você está concatenando três strings juntas, e o exemplo usando +é claramente o mais simples e legível, e, portanto, o recomendado.

%sou .format()são úteis se você deseja interpolar cadeias ou valores no meio de uma cadeia maior. Exemplo:

print "Hello %s, welcome to the computer!" % name

Nesse caso %s, é mais legível, pois você evita dividir a primeira string em vários segmentos. Especialmente se você estiver interpolando vários valores.

.join() é apropriado se você tiver uma sequência de tamanho variável de seqüências de caracteres e / ou quiser concatenar várias seqüências de caracteres com o mesmo separador.

JacquesB
fonte
2

Como a ordem das palavras pode mudar em diferentes idiomas, o formulário %sé obrigatório se você deseja oferecer suporte adequado à tradução de strings no seu software.

martjno
fonte