Puisque Python ne string
peut pas être changé, je me demandais comment concaténer une chaîne plus efficacement?
Je peux écrire comme ça:
s += stringfromelsewhere
ou comme ça:
s = []
s.append(somestring)
later
s = ''.join(s)
En écrivant cette question, j'ai trouvé un bon article sur le sujet.
http://www.skymind.com/~ocrow/python_string/
Mais c'est en Python 2.x., donc la question serait de savoir si quelque chose a changé en Python 3?
Réponses:
La meilleure façon d'ajouter une chaîne à une variable de chaîne est d'utiliser
+
ou+=
. C'est parce qu'il est lisible et rapide. Ils sont également tout aussi rapides, celui que vous choisissez est une question de goût, ce dernier est le plus courant. Voici les horaires avec letimeit
module:Cependant, ceux qui recommandent d'avoir des listes et de les ajouter, puis de les rejoindre, le font parce que l'ajout d'une chaîne à une liste est probablement très rapide par rapport à l'extension d'une chaîne. Et cela peut être vrai, dans certains cas. Voici, par exemple, un million d'annexes d'une chaîne à un caractère, d'abord à une chaîne, puis à une liste:
OK, il s'avère que même lorsque la chaîne résultante a un million de caractères, l'ajout était encore plus rapide.
Essayons maintenant d'ajouter une chaîne longue de mille caractères cent mille fois:
La chaîne de fin, par conséquent, finit par faire environ 100 Mo de long. C'était assez lent, l'ajout à une liste était beaucoup plus rapide. Que ce timing n'inclut pas la finale
a.join()
. Alors, combien de temps cela prendrait-il?Oups. Il s'avère que même dans ce cas, l'ajout / jointure est plus lent.
D'où vient donc cette recommandation? Python 2?
Eh bien, l'ajout / jointure est légèrement plus rapide là-bas si vous utilisez des chaînes extrêmement longues (ce que vous n'êtes généralement pas, qu'est-ce que vous auriez une chaîne de 100 Mo en mémoire?)
Mais le vrai point fort est Python 2.3. Où je ne vais même pas vous montrer les horaires, car c'est si lent que ce n'est pas encore fini. Ces tests prennent soudainement quelques minutes . À l'exception de l'ajout / jointure, qui est tout aussi rapide que sous Pythons ultérieurs.
Ouaip. La concaténation des cordes était très lente en Python à l'époque de la pierre. Mais sur 2.4, ce n'est plus le cas (ou du moins Python 2.4.7), donc la recommandation d'utiliser append / join est devenue obsolète en 2008, lorsque Python 2.3 a cessé d'être mis à jour, et vous auriez dû arrêter de l'utiliser. :-)
(Mise à jour: il s'avère que j'ai effectué les tests plus attentivement que l'utilisation
+
et+=
est également plus rapide pour deux chaînes sur Python 2.3. La recommandation à utiliser''.join()
doit être un malentendu)Cependant, c'est CPython. D'autres implémentations peuvent avoir d'autres préoccupations. Et c'est juste une autre raison pour laquelle l'optimisation prématurée est la racine de tout mal. N'utilisez pas une technique supposée "plus rapide" à moins que vous ne la mesuriez au préalable.
Par conséquent, la "meilleure" version pour effectuer la concaténation de chaînes consiste à utiliser + ou + = . Et si cela s'avère lent pour vous, ce qui est peu probable, faites autre chose.
Alors pourquoi est-ce que j'utilise beaucoup d'ajout / jointure dans mon code? Parce que parfois, c'est en fait plus clair. Surtout quand tout ce que vous devez concaténer ensemble doit être séparé par des espaces, des virgules ou des sauts de ligne.
la source
Si vous concaténez beaucoup de valeurs, alors ni l'un ni l'autre. Ajouter une liste coûte cher. Vous pouvez utiliser StringIO pour cela. Surtout si vous le construisez sur de nombreuses opérations.
Si une liste complète vous a déjà été renvoyée par une autre opération, utilisez simplement le
''.join(aList)
De la FAQ python: Quelle est la manière la plus efficace de concaténer plusieurs chaînes ensemble?
Edit: j'étais stupide et j'avais les résultats collés à l'envers, ce qui donne l'impression que l'ajout à une liste était plus rapide que cStringIO. J'ai également ajouté des tests pour bytearray / str concat, ainsi qu'une deuxième série de tests utilisant une liste plus longue avec des chaînes plus grandes. (python 2.7.3)
exemple de test ipython pour de grandes listes de chaînes
la source
cStringIO
n'existe pas dans Py3. Utilisezio.StringIO
plutôt.En Python> = 3.6, la nouvelle chaîne f est un moyen efficace de concaténer une chaîne.
la source
La méthode recommandée est toujours d'utiliser l'ajout et la jointure.
la source
Si les chaînes que vous concaténez sont des littéraux, utilisez la concaténation littérale des chaînes
Ceci est utile si vous souhaitez commenter une partie d'une chaîne (comme ci-dessus) ou si vous souhaitez utiliser des chaînes brutes ou des guillemets triples pour une partie d'un littéral mais pas pour la totalité.
Comme cela se produit au niveau de la couche de syntaxe, il utilise des opérateurs de concaténation zéro.
la source
Vous écrivez cette fonction
Ensuite, vous pouvez appeler simplement où vous voulez
la source
str_join = lambda *str_list: ''.join(s for s in str_list)
L'utilisation de la concaténation de chaîne sur place par «+» est LA pire méthode de concaténation en termes de stabilité et d'implémentation croisée car elle ne prend pas en charge toutes les valeurs. La norme PEP8 décourage cela et encourage l'utilisation de format (), join () et append () pour une utilisation à long terme.
Comme cité dans la section liée "Recommandations de programmation":
la source
Bien que quelque peu daté, Code Like a Pythonista: Idiomatic Python recommande
join()
plus+
dans cette section . Tout comme PythonSpeedPerformanceTips dans sa section sur la concaténation de chaînes , avec l'avertissement suivant:la source
Comme @jdi le mentionne, la documentation Python suggère d'utiliser
str.join
ouio.StringIO
pour la concaténation de chaînes. Et dit qu'un développeur devrait s'attendre+=
à un temps quadratique dans une boucle, même s'il y a une optimisation depuis Python 2.4. Comme le dit cette réponse:Je vais montrer un exemple de code du monde réel qui reposait naïvement sur
+=
cette optimisation, mais il ne s'appliquait pas. Le code ci-dessous convertit un itérable de chaînes courtes en plus gros morceaux à utiliser dans une API en bloc.Ce code peut littéralement fonctionner pendant des heures en raison de la complexité temporelle quadratique. Voici des alternatives avec des structures de données suggérées:
Et un micro-benchmark:
la source
Vous pouvez le faire de différentes manières.
J'ai créé ce petit résumé à travers les articles suivants.
la source
mon cas d'utilisation était légèrement différent. J'ai dû construire une requête où plus de 20 champs étaient dynamiques. J'ai suivi cette approche en utilisant la méthode de formatage
c'était relativement plus simple pour moi au lieu d'utiliser + ou d'autres moyens
la source
Vous pouvez également l'utiliser (plus efficace). ( /software/304445/why-is-s-better-than-for-concatenation )
la source