Um antipadrão comum em Python é concatenar uma sequência de strings usando +
um loop. Isso é ruim porque o intérprete Python precisa criar um novo objeto de seqüência de caracteres para cada iteração e acaba levando tempo quadrático. (Versões recentes do CPython aparentemente podem otimizar isso em alguns casos, mas outras implementações não podem, então os programadores são desencorajados a confiar nisso.) ''.join
É o caminho certo para fazer isso.
No entanto, eu ouvi dizer ( incluindo aqui no Stack Overflow ) que você nunca deve usar +
para concatenação de strings, mas sempre usar ''.join
ou uma string de formato. Não entendo por que esse é o caso se você está apenas concatenando duas strings. Se meu entendimento está correto, não deve levar tempo quadrático, e acho que a + b
é mais limpo e mais legível que um ''.join((a, b))
ou outro '%s%s' % (a, b)
.
É uma boa prática usar +
para concatenar duas seqüências de caracteres? Ou existe um problema que não conheço?
+
é mais rápido ou mais lento? E porque?In [2]: %timeit "a"*80 + "b"*80
1000000 loops, best of 3: 356 ns per loop
In [3]: %timeit "%s%s" % ("a"*80, "b"*80)
1000000 loops, best of 3: 907 ns per loop
In [3]: %timeit "%s%s" % (a, b) 1000000 loops, best of 3: 590 ns per loop
In [4]: %timeit a + b 10000000 loops, best of 3: 147 ns per loop
__str__
. Veja minha resposta para exemplos.Respostas:
Não há nada errado em concatenar duas strings com
+
. Na verdade, é mais fácil ler do que''.join([a, b])
.Você está certo de que concatenar mais de 2 strings com
+
é uma operação O (n ^ 2) (em comparação com O (n) parajoin
) e, portanto, se torna ineficiente. No entanto, isso não tem a ver com o uso de um loop. Evena + b + c + ...
é O (n ^ 2), o motivo é que cada concatenação produz uma nova string.O CPython2.4 e superior tentam mitigar isso, mas ainda é aconselhável usar
join
ao concatenar mais de 2 strings.fonte
.join
leva um iterável, então ambos.join([a,b])
e.join((a,b))
são válidos.+
ou+=
a resposta aceita (de 2013) em stackoverflow.com/a/12171382/378826 (de Lennart Regebro), mesmo para o CPython 2.3+, e escolher apenas o padrão "acrescentar / associar" se este indicador mais claro expuser o idéia para a solução do problema em questão.O operador Plus é uma solução perfeitamente adequada para concatenar duas seqüências de caracteres Python. Mas se você continuar adicionando mais de duas strings (n> 25), poderá pensar em outra coisa.
''.join([a, b, c])
O truque é uma otimização de desempenho.fonte
append()
strings a uma lista.n > 25
. Os seres humanos precisam de pontos de referência para começar em algum lugar.A suposição de que nunca se deve usar + para concatenação de strings, mas sempre usar '' .join pode ser um mito. É verdade que o uso
+
cria cópias temporárias desnecessárias do objeto de sequência imutável, mas o outro fato não citado é que a chamadajoin
em um loop geralmente adicionaria a sobrecarga defunction call
. Vamos dar o seu exemplo.Crie duas listas, uma a partir da questão SO vinculada e outra uma maior fabricada
Vamos criar duas funções
UseJoin
eUsePlus
usar a respectivajoin
e a+
funcionalidade.Permite executar o timeit com a primeira lista
Eles têm quase o mesmo tempo de execução.
Vamos usar cProfile
E parece que o uso de Join resulta em chamadas de funções desnecessárias que podem aumentar a sobrecarga.
Agora voltando à pergunta. Devemos desencorajar o uso do
+
excessojoin
em todos os casos?Eu acredito que não, as coisas devem ser levadas em consideração
E, fora do curso, em uma otimização pré-amadurecida no desenvolvimento é ruim.
fonte
join
dentro do próprio loop - em vez disso, o loop geraria uma sequência que seria passada para a junção.Ao trabalhar com várias pessoas, às vezes é difícil saber exatamente o que está acontecendo. O uso de uma string de formato em vez da concatenação pode evitar um incômodo específico que aconteceu várias vezes conosco:
Digamos, uma função requer um argumento e você a escreve esperando obter uma string:
Portanto, essa função pode ser usada com bastante frequência em todo o código. Seus colegas de trabalho talvez saibam exatamente o que fazem, mas não necessariamente estejam totalmente atualizados nas informações internas e talvez não saibam que a função espera uma string. E assim eles podem acabar com isso:
Não haveria problema se você apenas usasse uma string de formato:
O mesmo vale para todos os tipos de objetos que definem
__str__
, que também podem ser passados:Então, sim: se você pode usar uma string de formato, faça isso e aproveite o que o Python tem a oferecer.
fonte
+
.zeta = u"a\xac\u1234\u20ac\U00008000"
- então você teria que usarprint 'bar: ' + unicode(zeta)
para garantir que não haja erros.%s
não é certo, sem ter que pensar sobre isso, e é muito mais curto"bar: %s"
podem ser traduzidos para"zrb: %s br"
outro idioma. A%s
versão será apenas o trabalho, mas a versão String-concat se tornaria uma bagunça para lidar com todos os casos e os seus tradutores que agora tem duas traduções independentes para lidar comdef
.Eu fiz um teste rápido:
e cronometrou:
Aparentemente, há uma otimização para o
a = a + b
caso. Não exibe o tempo O (n ^ 2) como se pode suspeitar.Portanto, pelo menos em termos de desempenho, o uso
+
é bom.fonte
De acordo com os documentos do Python, o uso de str.join () fornecerá consistência de desempenho em várias implementações do Python. Embora o CPython otimize o comportamento quadrático de s = s + t, outras implementações do Python podem não.
Tipos de sequência nos documentos Python (veja a nota de rodapé [6])
fonte
Eu uso o seguinte com python 3.8
fonte
'' .join ([a, b]) é a melhor solução que + .
Como o código deve ser escrito de uma maneira que não prejudique outras implementações do Python (PyPy, Jython, IronPython, Cython, Psyco e outras)
O formulário a + = b ou a = a + b é frágil mesmo no CPython e não está presente em implementações que não usam refcounting (a contagem de referência é uma técnica de armazenar o número de referências, ponteiros ou identificadores em um recurso, como um objeto, bloco de memória, espaço em disco ou outro recurso )
https://www.python.org/dev/peps/pep-0008/#programming-recommendations
fonte
a += b
funciona em todas as implementações do Python, mas em algumas delas leva tempo quadrático quando feito dentro de um loop ; a pergunta era sobre concatenação de strings fora de um loop.