Existe algum método eficiente de concatenação de cadeias de massa em Python (como StringBuilder em C # ou StringBuffer em Java)? Encontrei os seguintes métodos aqui :
- Concatenação simples usando
+
- Usando lista de strings e
join
método de - Usando
UserString
deMutableString
módulo - Usando matriz de caracteres e o
array
módulo - Usando
cStringIO
doStringIO
módulo
Mas o que os especialistas usam ou sugerem e por quê?
f''
seqüências de formato que serão mais rápidas do que quaisquer alternativas nas versões anteriores do Python.Respostas:
Você pode estar interessado nisso: Uma anedota de otimização de Guido. Embora valha a pena lembrar também que este é um artigo antigo e é anterior à existência de coisas como
''.join
(embora eu achestring.joinfields
seja mais ou menos o mesmo)Com base nisso, o
array
módulo pode ser mais rápido se você conseguir resolver o problema. Mas''.join
provavelmente é rápido o suficiente e tem o benefício de ser idiomático e, portanto, mais fácil para outros programadores de python entenderem.Finalmente, a regra de ouro da otimização: não otimize, a menos que você saiba que precisa, e meça em vez de adivinhar.
Você pode medir diferentes métodos usando o
timeit
módulo. Isso pode lhe dizer qual é o mais rápido, em vez de estranhos aleatórios na internet fazendo suposições.fonte
.join()
? A questão principal é: a) cria uma cópia da string para concatenação (semelhante as = s + 'abc'
), que requer tempo de execução O (n) ou b) simplesmente anexa à string existente sem criar uma cópia, o que requer O (1) ?''.join(sequenceofstrings)
é o que geralmente funciona melhor - mais simples e rápido.fonte
''.join(sequence)
idioma. É especialmente útil produzir listas separadas por vírgula:', '.join([1, 2, 3])
fornece a sequência'1, 2, 3'
."".join(chr(x) for x in xrange(65,91))
--- neste caso, o argumento para ingressar é um iterador, criado através de uma expressão geradora. Não existe uma lista temporária que seja construída.O Python 3.6 mudou o jogo para concatenação de string de componentes conhecidos com Interpolação de String Literal .
Dado o caso de teste da resposta de mkoistinen , ter strings
Os candidatos são
f'http://{domain}/{lang}/{path}'
- 0,151 µs'http://%s/%s/%s' % (domain, lang, path)
- 0,321 µs'http://' + domain + '/' + lang + '/' + path
- 0,356 µs''.join(('http://', domain, '/', lang, '/', path))
- 0,249 µs (observe que a construção de uma tupla de comprimento constante é um pouco mais rápida que a construção de uma lista de comprimento constante).Portanto, atualmente, o código mais curto e mais bonito possível também é o mais rápido.
Nas versões alfa do Python 3.6, a implementação de
f''
strings era a mais lenta possível - na verdade, o código de bytes gerado é praticamente equivalente ao''.join()
caso de chamadas desnecessárias parastr.__format__
quais, sem argumentos, retornariaself
inalterado. Essas ineficiências foram tratadas antes da 3.6 final.A velocidade pode ser contrastada com o método mais rápido do Python 2, que é a
+
concatenação no meu computador; e isso leva 0,203 µs com cadeias de 8 bits e 0,259 µs se as cadeias forem todas Unicode.fonte
Depende do que você está fazendo.
Após o Python 2.5, a concatenação de strings com o operador + é bastante rápida. Se você está apenas concatenando alguns valores, usar o operador + funciona melhor:
No entanto, se você estiver montando uma string em um loop, será melhor usar o método de junção de lista:
... mas observe que é necessário reunir um número relativamente alto de strings antes que a diferença se torne perceptível.
fonte
De acordo com a resposta de John Fouhy, não otimize a menos que você precise, mas se você está aqui e faz essa pergunta, pode ser precisamente porque você precisa . No meu caso, eu precisava montar alguns URLs a partir de variáveis de string ... rápido. Percebi que ninguém (até agora) parece considerar o método de formato de string, então pensei em tentar isso e, principalmente por um interesse moderado, pensei em lançar o operador de interpolação de string para um bom medidor. Para ser sincero, não achei que um desses fosse empilhar em uma operação direta '+' ou em '' .join (). Mas adivinhem? No meu sistema Python 2.7.5, o operador de interpolação de strings governa todos eles e string.format () é o pior executor:
Os resultados:
Se eu usar um domínio mais curto e um caminho mais curto, a interpolação ainda vence. A diferença é mais acentuada, porém, com cordas mais longas.
Agora que eu tinha um bom script de teste, também testei no Python 2.6, 3.3 e 3.4, eis os resultados. No Python 2.6, o operador positivo é o mais rápido! No Python 3, a participação vence. Nota: esses testes são muito repetíveis no meu sistema. Portanto, 'plus' é sempre mais rápido no 2.6, 'intp' é sempre mais rápido no 2.7 e 'join' é sempre mais rápido no Python 3.x.
Lição aprendida:
tl; dr:
fonte
f'http://{domain}/{lang}/{path}'
.format()
tem três formas, a fim de rápido para lento:"{}".format(x)
,"{0}".format(x)
,"{x}".format(x=x)
depende muito dos tamanhos relativos da nova string após cada nova concatenação. Com o
+
operador, para cada concatenação é criada uma nova string. Se as cadeias intermediárias forem relativamente longas, elas+
se tornarão cada vez mais lentas porque a nova cadeia intermediária está sendo armazenada.Considere este caso:
Resultados
1 0.00493192672729
2 0.000509023666382
3 0.00042200088501
4 0.000482797622681
No caso de 1 e 2, adicionamos uma string grande e o join () executa cerca de 10 vezes mais rápido. Nos casos 3 e 4, adicionamos uma string pequena e o '+' executa um pouco mais rápido
fonte
Eu me deparei com uma situação em que precisava ter uma sequência anexável de tamanho desconhecido. Estes são os resultados de referência (python 2.7.3):
Isso parece mostrar que '+ =' é o mais rápido. Os resultados do link skymind estão um pouco desatualizados.
(Percebo que o segundo exemplo não está completo, a lista final precisaria ser unida. Isso mostra, no entanto, que simplesmente preparar a lista leva mais tempo que a sequência concat.)
fonte
Um ano depois, vamos testar a resposta de mkoistinen com o python 3.4.3:
Nada mudou. A associação ainda é o método mais rápido. Com o intp sendo a melhor escolha em termos de legibilidade, você pode querer usá-lo.
fonte
Inspirado nos benchmarks do @ JasonBaker, aqui está um simples que compara 10
"abcdefghijklmnopqrstuvxyz"
strings, mostrando que.join()
é mais rápido; mesmo com este pequeno aumento de variáveis:Catenação
Junte-se
fonte
Para um pequeno conjunto de strings curtas (ou seja, 2 ou 3 strings com no máximo alguns caracteres), o plus ainda é muito mais rápido. Usando o maravilhoso script de mkoistinen em Python 2 e 3:
Portanto, quando seu código estiver executando um grande número de pequenas concatenações separadas, plus é a maneira preferida se a velocidade for crucial.
fonte
Provavelmente "novas strings f no Python 3.6" são a maneira mais eficiente de concatenar strings.
Usando% s
Usando .format
Usando f
Fonte: https://realpython.com/python-f-strings/
fonte