Existe-t-il une méthode de concaténation de chaînes de masse efficace en Python (comme StringBuilder en C # ou StringBuffer en Java)? J'ai trouvé les méthodes suivantes ici :
- Concaténation simple utilisant
+
- Utilisation de la liste de chaînes et de la
join
méthode - Utilisation
UserString
duMutableString
module - Utilisation du tableau de caractères et du
array
module - Utilisation
cStringIO
duStringIO
module
Mais qu'est-ce que vos experts utilisent ou suggèrent et pourquoi?
f''
chaînes de format qui seront plus rapides que toutes les alternatives des versions précédentes de Python.Réponses:
Cela pourrait vous intéresser: Une anecdote d'optimisation par Guido. Même s'il vaut la peine de se rappeler qu'il s'agit d'un ancien article et qu'il est antérieur à l'existence de choses comme
''.join
(même si je suppose questring.joinfields
c'est plus ou moins la même chose)Sur la base de cela, le
array
module peut être le plus rapide si vous pouvez y exprimer votre problème. Mais''.join
c'est probablement assez rapide et a l'avantage d'être idiomatique et donc plus facile à comprendre pour les autres programmeurs python.Enfin, la règle d'or de l'optimisation: n'optimisez que si vous savez que vous en avez besoin et mesurez plutôt que de deviner.
Vous pouvez mesurer différentes méthodes à l'aide du
timeit
module. Cela peut vous dire lequel est le plus rapide, au lieu que des inconnus aléatoires sur Internet fassent des suppositions.la source
.join()
? La question principale est de savoir si a) créer une copie de la chaîne pour la concaténation (similaire às = s + 'abc'
), qui nécessite l'exécution O (n), ou b) simplement ajouter à la chaîne existante sans créer de copie, ce qui nécessite O (1) ?''.join(sequenceofstrings)
est ce qui fonctionne le mieux - le plus simple et le plus rapidela source
''.join(sequence)
idiome. Il est particulièrement utile de produire des listes séparées par des virgules:', '.join([1, 2, 3])
donne la chaîne'1, 2, 3'
."".join(chr(x) for x in xrange(65,91))
--- dans ce cas, l'argument à joindre est un itérateur, créé via une expression de générateur. Il n'y a pas de liste temporaire qui se construit.Python 3.6 a changé le jeu pour la concaténation de chaînes de composants connus avec l' interpolation de chaînes littérales .
Compte tenu du cas de test de la réponse de mkoistinen , avoir des chaînes
Les prétendants sont
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 (notez que la construction d'un tuple de longueur constante est légèrement plus rapide que la construction d'une liste de longueur constante).Ainsi actuellement, le code le plus court et le plus beau possible est également le plus rapide.
Dans les versions alpha de Python 3.6, l'implémentation des
f''
chaînes était la plus lente possible - en fait, le code d'octet généré est à peu près équivalent au''.join()
cas des appels inutilesstr.__format__
auxquels sans arguments retourneraient simplementself
inchangés. Ces inefficacités ont été corrigées avant la version 3.6 final.La vitesse peut être comparée à la méthode la plus rapide pour Python 2, qui est la
+
concaténation sur mon ordinateur; et cela prend 0,203 µs avec des chaînes de 8 bits et 0,259 µs si les chaînes sont toutes Unicode.la source
Cela dépend de ce que vous faites.
Après Python 2.5, la concaténation de chaînes avec l'opérateur + est assez rapide. Si vous ne faites que concaténer quelques valeurs, l'utilisation de l'opérateur + fonctionne mieux:
Cependant, si vous assemblez une chaîne dans une boucle, il vaut mieux utiliser la méthode de jonction de liste:
... mais notez que vous devez assembler un nombre relativement élevé de chaînes avant que la différence ne devienne perceptible.
la source
Selon la réponse de John Fouhy, n'optimisez pas sauf si vous devez le faire, mais si vous êtes ici et que vous posez cette question, c'est peut-être précisément parce que vous devez le faire . Dans mon cas, j'avais besoin d'assembler des URL à partir de variables de chaîne ... rapidement. Je n'ai remarqué que personne (jusqu'à présent) ne semble envisager la méthode du format de chaîne, alors j'ai pensé essayer cela et, surtout pour un intérêt léger, j'ai pensé que je jetterais l'opérateur d'interpolation de chaîne là-dedans pour un bon mesureur. Pour être honnête, je ne pensais pas que l'un ou l'autre de ces éléments s'empilerait jusqu'à une opération directe «+» ou un «.join ()». Mais devinez quoi? Sur mon système Python 2.7.5, l'opérateur d'interpolation de chaîne les règle tous et string.format () est le moins performant:
Les resultats:
Si j'utilise un domaine plus court et un chemin plus court, l'interpolation l'emporte toujours. La différence est cependant plus prononcée avec des cordes plus longues.
Maintenant que j'avais un joli script de test, j'ai également testé sous Python 2.6, 3.3 et 3.4, voici les résultats. En Python 2.6, l'opérateur plus est le plus rapide! Sur Python 3, rejoindre l'emporte. Remarque: ces tests sont très répétables sur mon système. Ainsi, «plus» est toujours plus rapide sur 2.6, «intp» est toujours plus rapide sur 2.7 et «join» est toujours plus rapide sur Python 3.x.
Leçon apprise:
tl; dr:
la source
f'http://{domain}/{lang}/{path}'
.format()
a trois formes, afin de rapide à lent:"{}".format(x)
,"{0}".format(x)
,"{x}".format(x=x)
cela dépend à peu près des tailles relatives de la nouvelle chaîne après chaque nouvelle concaténation. Avec l'
+
opérateur, pour chaque concaténation, une nouvelle chaîne est créée. Si les chaînes intermédiaires sont relativement longues, le+
devient de plus en plus lent car la nouvelle chaîne intermédiaire est stockée.Considérez ce cas:
Résultats
1 0,00493192672729
2 0,000509023666382
3 0,00042200088501
4 0,000482797622681
Dans le cas de 1 et 2, nous ajoutons une grande chaîne et join () fonctionne environ 10 fois plus rapidement. Dans les cas 3 et 4, nous ajoutons une petite chaîne, et '+' fonctionne légèrement plus vite
la source
Je suis tombé sur une situation où je devais avoir une chaîne appendable de taille inconnue. Voici les résultats du benchmark (python 2.7.3):
Cela semble montrer que «+ =» est le plus rapide. Les résultats du lien skymind sont un peu dépassés.
(Je me rends compte que le deuxième exemple n'est pas complet, la liste finale devrait être jointe. Cela montre cependant que la simple préparation de la liste prend plus de temps que la chaîne concat.)
la source
Un an plus tard, testons la réponse de mkoistinen avec python 3.4.3:
Rien n'a changé. Join est toujours la méthode la plus rapide. Avec intp étant sans doute le meilleur choix en termes de lisibilité, vous voudrez peut-être néanmoins utiliser intp.
la source
Inspiré des benchmarks de @ JasonBaker, en voici un simple comparant 10
"abcdefghijklmnopqrstuvxyz"
chaînes, montrant que.join()
c'est plus rapide; même avec cette petite augmentation des variables:Caténation
Joindre
la source
Pour un petit ensemble de chaînes courtes (c'est-à-dire 2 ou 3 chaînes de pas plus de quelques caractères), plus est encore beaucoup plus rapide. Utilisation du merveilleux script de mkoistinen dans Python 2 et 3:
Ainsi, lorsque votre code effectue un grand nombre de petites concaténations séparées, le plus est le moyen préféré si la vitesse est cruciale.
la source
Les "nouvelles f-strings en Python 3.6" sont probablement le moyen le plus efficace de concaténer des chaînes.
Utilisation de% s
Utiliser .format
Utilisation de f
Source: https://realpython.com/python-f-strings/
la source