En Python, le lieu et le moment de l'utilisation de la concaténation de chaînes par rapport à la substitution de chaînes m'échappent. Étant donné que la concaténation des cordes a connu de grandes améliorations de performances, est-ce (de plus en plus) une décision stylistique plutôt que pratique?
Pour un exemple concret, comment gérer la construction d'URI flexibles:
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: Il y a également eu des suggestions pour joindre une liste de chaînes et pour utiliser la substitution nommée. Ce sont des variantes sur le thème central, qui est, quelle est la bonne façon de le faire à quel moment? Merci pour les réponses!
python
string
string-concatenation
gotgenes
la source
la source
Réponses:
La concaténation est (nettement) plus rapide selon ma machine. Mais stylistiquement, je suis prêt à payer le prix de la substitution si la performance n'est pas critique. Eh bien, et si j'ai besoin d'un formatage, il n'est même pas nécessaire de poser la question ... il n'y a pas d'autre choix que d'utiliser l'interpolation / la création de modèles.
la source
N'oubliez pas la substitution nommée:
la source
Méfiez-vous de la concaténation de chaînes en boucle! Le coût de la concaténation de chaînes est proportionnel à la longueur du résultat. Looping vous mène directement au pays de N-squared. Certains langages optimiseront la concaténation à la chaîne la plus récemment allouée, mais il est risqué de compter sur le compilateur pour optimiser votre algorithme quadratique jusqu'à linéaire. Il est préférable d'utiliser la primitive (
join
?) Qui prend une liste entière de chaînes, effectue une allocation unique et les concatène toutes en une seule fois.la source
"Comme la concaténation de chaînes a vu de grandes améliorations dans les performances ..."
Si la performance compte, c'est bon à savoir.
Cependant, les problèmes de performances que j'ai vus ne se résument jamais à des opérations de chaîne. J'ai généralement eu des problèmes avec les E / S, le tri et les opérations O ( n 2 ) étant les goulots d'étranglement.
Tant que les opérations sur les chaînes ne sont pas les limites des performances, je m'en tiendrai à des choses évidentes. Surtout, c'est la substitution quand il s'agit d'une ligne ou moins, la concaténation quand cela a du sens et un outil de modèle (comme Mako) quand il est grand.
la source
Ce que vous souhaitez concaténer / interpoler et la manière dont vous souhaitez formater le résultat doivent guider votre décision.
L'interpolation de chaîne vous permet d'ajouter facilement une mise en forme. En fait, votre version d'interpolation de chaîne ne fait pas la même chose que votre version de concaténation; il ajoute en fait une barre oblique supplémentaire avant le
q_num
paramètre. Pour faire la même chose, vous devrez écrirereturn DOMAIN + QUESTIONS + "/" + str(q_num)
dans cet exemple.L'interpolation facilite le formatage des chiffres;
"%d of %d (%2.2f%%)" % (current, total, total/current)
serait beaucoup moins lisible sous forme de concaténation.La concaténation est utile lorsque vous n'avez pas un nombre fixe d'éléments à définir.
Sachez également que Python 2.6 introduit une nouvelle version d'interpolation de chaîne, appelée création de modèles de chaînes :
La création de modèles de chaînes devrait éventuellement remplacer% -interpolation, mais cela ne se produira pas avant un certain temps, je pense.
la source
Je testais juste la vitesse de différentes méthodes de concaténation / substitution de chaînes par curiosité. Une recherche google sur le sujet m'a amené ici. J'ai pensé publier les résultats de mes tests dans l'espoir que cela aiderait quelqu'un à décider.
... Après avoir exécuté
runtests((percent_, format_, format2_, concat_), runs=5)
, j'ai trouvé que la méthode% était environ deux fois plus rapide que les autres sur ces petites chaînes. La méthode concat était toujours la plus lente (à peine). Il y avait de très petites différences lors du changement de position dans laformat()
méthode, mais le changement de position était toujours au moins 0,01 plus lent que la méthode de format normal.Échantillon de résultats de test:
Je les ai exécutés parce que j'utilise la concaténation de chaînes dans mes scripts, et je me demandais quel en était le coût. Je les ai exécutés dans des ordres différents pour m'assurer que rien n'interférait, ou obtenir de meilleures performances en premier ou en dernier. D'un autre côté, j'ai
"%s" + ("a" * 1024)
ajouté des générateurs de chaînes plus longues dans ces fonctions comme et le concat régulier était presque 3 fois plus rapide (1,1 contre 2,8) que l'utilisation des méthodesformat
et%
. Je suppose que cela dépend des cordes et de ce que vous essayez de réaliser. Si les performances comptent vraiment, il vaudrait peut-être mieux essayer différentes choses et les tester. J'ai tendance à choisir la lisibilité plutôt que la vitesse, à moins que la vitesse ne devienne un problème, mais ce n'est que moi. Donc, je n'ai pas aimé mon copier / coller, j'ai dû mettre 8 espaces sur tout pour que tout soit correct. J'utilise habituellement 4.la source
str.format()
et au-str.join()
dessus de la concaténation normale. Je garde également un œil sur les «f-strings» de PEP 498 , qui ont récemment été acceptées. En ce qui concerne lesstr()
appels affectant les performances, je suis sûr que vous avez raison. Je n'avais aucune idée du coût des appels de fonction à l'époque. Je pense toujours que des tests doivent être effectués en cas de doute.join_(): return ''.join(["test ", str(1), ", with number ", str(2)])
, il semblejoin
également plus lent que le pourcentage.Rappelez-vous, les décisions stylistiques sont des décisions pratiques, si jamais vous prévoyez de maintenir ou de déboguer votre code :-) Il y a une citation célèbre de Knuth (citant peut-être Hoare?): «Nous devrions oublier les petits gains d'efficacité, disons environ 97% du temps: L'optimisation prématurée est la racine de tout Mal."
Tant que vous faites attention de ne pas (dire) transformer une tâche O (n) en une tâche O (n 2 ), j'irais avec celle que vous trouvez la plus facile à comprendre.
la source
J'utilise la substitution partout où je peux. Je n'utilise la concaténation que si je construis une chaîne dans, par exemple, une boucle for.
la source
En fait, la bonne chose à faire, dans ce cas (créer des chemins), est d'utiliser
os.path.join
. Pas de concaténation ou d'interpolation de chaînesla source