Em Python, me escapa onde e quando usar concatenação de string versus substituição de string. Como a concatenação de strings sofreu grandes aumentos no desempenho, esta (se tornando mais) uma decisão estilística em vez de prática?
Para um exemplo concreto, como lidar com a construção de URIs flexíveis:
DOMAIN = 'http://stackoverflow.com'
QUESTIONS = '/questions'
def so_question_uri_sub(q_num):
return "%s%s/%d" % (DOMAIN, QUESTIONS, q_num)
def so_question_uri_cat(q_num):
return DOMAIN + QUESTIONS + '/' + str(q_num)
Edit: Também houve sugestões sobre como juntar uma lista de strings e para usar a substituição nomeada. São variantes do tema central, qual seja, qual é a maneira certa de fazê-lo e em que momento? Obrigado pelas respostas!
python
string
string-concatenation
Gotgenes
fonte
fonte
Respostas:
A concatenação é (significativamente) mais rápida de acordo com minha máquina. Mas, estilisticamente, estou disposto a pagar o preço da substituição se o desempenho não for crítico. Bem, e se eu precisar de formatação, não há necessidade nem de fazer a pergunta ... não há opção a não ser usar interpolação / modelagem.
fonte
Não se esqueça da substituição nomeada:
fonte
Tenha cuidado ao concatenar strings em um loop! O custo da concatenação de strings é proporcional ao comprimento do resultado. O loop leva você direto para a terra do N-quadrado. Algumas linguagens otimizarão a concatenação para a string alocada mais recentemente, mas é arriscado contar com o compilador para otimizar seu algoritmo quadrático até linear. Melhor usar o primitivo (
join
?) Que pega uma lista inteira de strings, faz uma única alocação e concatena todas de uma vez.fonte
"Como a concatenação de strings teve grandes aumentos de desempenho ..."
Se o desempenho for importante, é bom saber.
No entanto, os problemas de desempenho que vi nunca se resumem a operações de string. Geralmente tenho problemas com operações de E / S, classificação e operações O ( n 2 ) sendo os gargalos.
Até que as operações de string sejam os limitadores de desempenho, vou me ater ao que é óbvio. Principalmente, isso é substituição quando é uma linha ou menos, concatenação quando faz sentido e uma ferramenta de modelo (como Mako) quando é grande.
fonte
O que você deseja concatenar / interpolar e como deseja formatar o resultado deve orientar sua decisão.
A interpolação de strings permite adicionar formatação facilmente. Na verdade, sua versão de interpolação de string não faz a mesma coisa que sua versão de concatenação; na verdade, ele adiciona uma barra extra antes do
q_num
parâmetro. Para fazer a mesma coisa, você teria que escreverreturn DOMAIN + QUESTIONS + "/" + str(q_num)
nesse exemplo.A interpolação torna mais fácil formatar números;
"%d of %d (%2.2f%%)" % (current, total, total/current)
seria muito menos legível na forma de concatenação.A concatenação é útil quando você não tem um número fixo de itens para sequenciar.
Além disso, saiba que o Python 2.6 apresenta uma nova versão de interpolação de string, chamada de modelagem de string :
A modelagem de strings está programada para substituir a% -interpolação, mas isso não acontecerá por um bom tempo, eu acho.
fonte
Eu estava apenas testando a velocidade de diferentes métodos de concatenação / substituição de strings por curiosidade. Uma pesquisa no google sobre o assunto me trouxe aqui. Pensei em postar os resultados do meu teste na esperança de que ajudasse alguém a decidir.
... Depois de executar
runtests((percent_, format_, format2_, concat_), runs=5)
, descobri que o método% era cerca de duas vezes mais rápido que os outros nessas pequenas strings. O método concat sempre foi o mais lento (quase imperceptível). Havia diferenças muito pequenas ao alternar as posições noformat()
método, mas alternar as posições sempre foi pelo menos 0,01 mais lento do que o método de formato regular.Amostra de resultados de teste:
Eu os executei porque uso concatenação de string em meus scripts e queria saber qual era o custo. Eu os executei em ordens diferentes para ter certeza de que nada estava interferindo ou obtendo um melhor desempenho sendo o primeiro ou o último. Em uma nota lateral, eu adicionei alguns geradores de string mais longos para funções como
"%s" + ("a" * 1024)
concat regular e foi quase 3 vezes mais rápido (1,1 vs 2,8) do que usar os métodosformat
e%
. Acho que depende das cordas e do que você está tentando alcançar. Se o desempenho realmente importa, talvez seja melhor tentar coisas diferentes e testá-las. Eu tendo a escolher a legibilidade ao invés da velocidade, a menos que a velocidade se torne um problema, mas isso sou só eu. ASSIM não gostei do meu copiar / colar, eu tive que colocar 8 espaços em tudo para que ficasse certo. Eu geralmente uso 4.fonte
str.format()
estr.join()
sobre a concatenação normal. Também estou de olho nos 'f-strings' do PEP 498 , que foi aceito recentemente. Quanto àsstr()
ligações que afetam o desempenho, tenho certeza de que você está certo. Eu não tinha ideia de como as chamadas de função eram caras naquela época. Ainda acho que os testes devem ser feitos quando há alguma dúvida.join_(): return ''.join(["test ", str(1), ", with number ", str(2)])
, parece quejoin
também é mais lento do que a porcentagem.Lembre-se de que as decisões estilísticas são decisões práticas, se você planeja manter ou depurar seu código :-) Há uma citação famosa de Knuth (possivelmente citando Hoare?): "Devemos esquecer as pequenas eficiências, digamos cerca de 97% das vezes: Otimização prematura é a raiz de todo o mal."
Contanto que você tome cuidado para não (digamos) transformar uma tarefa O (n) em uma tarefa O (n 2 ), eu faria a que você achar mais fácil de entender.
fonte
Eu uso a substituição sempre que posso. Eu só uso a concatenação se estou construindo uma string em, digamos, um loop for.
fonte
Na verdade, a coisa certa a fazer, neste caso (construir caminhos) é usar
os.path.join
. Não é concatenação de string ou interpolaçãofonte