Pourquoi% s est-il meilleur que + pour la concaténation?

88

Je comprends que nous devrions utiliser %spour concaténer une chaîne plutôt qu'en +Python.

Je pourrais faire n'importe lequel de:

hello = "hello"
world = "world"

print hello + " " + world
print "%s %s" % (hello, world)
print "{} {}".format(hello, world)
print ' '.join([hello, world])

Mais pourquoi devrais-je utiliser autre chose que le +? Il est plus rapide d’écrire une concaténation simple +. Ensuite, si vous regardez la chaîne de formatage, vous spécifiez les types, par exemple %s, %det autres. Je comprends qu'il pourrait être préférable d’être explicite sur le type.

Mais ensuite, j'ai lu que l'utilisation +de la concaténation devrait être évitée même s'il est plus facile de taper. Existe-t-il une raison claire pour que les chaînes soient concaténées de l'une de ces manières?

Niklas Rosencrantz
la source
29
Qui t'a dit que c'était mieux?
yannis
3
%sest pas concaténation, il est une spécification de conversion pour la mise en forme de chaîne dérivée de C de printf(3). Il existe des cas d'utilisation de cet opérateur ou d'un opérateur de concaténation; que vous utilisez doit être basé sur le jugement de la situation, pas de dogme. Comme il est facile d'écrire le code, cela n'a aucune importance, car vous ne le ferez qu'une fois.
Blrfl
J'ai recentré la question sur python uniquement (bien que je ne sois pas une personne python et que des problèmes subsistent dans le code). Assurez-vous qu'il s'agit bien de la question que vous posez, apportez les mises à jour appropriées et envisagez de poser une question différente si vous êtes intéressé par C ou Java.
12
Et maintenant nous avons les cordes f supérieures ! print(f"{hello} {world}"), a la lisibilité de la concaténation puisque les variables sont vues là où elles apparaissent dans la chaîne, et est plus rapide que str.format.
Enrico Borba

Réponses:

88
  1. Lisibilité. La syntaxe de chaîne de format est plus lisible, car elle sépare le style des données. De plus, en Python, la %ssyntaxe contraindra automatiquement tous les non- strtypes à str; tandis que la concaténation fonctionne uniquement avec str, et vous ne pouvez pas concaténer stravec int.

  2. Performance. En Python strest immuable, les chaînes gauche et droite doivent donc être copiées dans la nouvelle chaîne pour chaque paire de concaténation. Si vous concaténez quatre chaînes de longueur 10, vous copiez (10 + 10) + ((10 + 10) + 10) + (((10 + 10) + 10) + 10) = 90 caractères, au lieu de 40 caractères. personnages. Et les choses empirent de façon quadratique à mesure que le nombre et la taille de la chaîne augmentent. Java optimise parfois ce cas en transformant la série de concaténation à utiliser StringBuilder, contrairement à CPython.

  3. Dans certains cas d'utilisation, la bibliothèque de journalisation fournit une API qui utilise une chaîne de format pour créer la chaîne d'entrée de journal lazily ( logging.info("blah: %s", 4)). Ceci est idéal pour améliorer les performances si la bibliothèque de journalisation décide que l'entrée de journal actuelle sera supprimée par un filtre de journalisation, de sorte qu'il n'est pas nécessaire de formater la chaîne.

Lie Ryan
la source
31
Avez-vous une source scientifique ou empirique pour # 1? Parce que je pense que c'est beaucoup moins lisible (surtout avec plus de 2 ou 3 arguments)
Lovis
4
@ L.Möller: Je ne suis pas sûr du type de source que vous attendez de ce qui est finalement une expérience subjective (facilité de lecture), mais si vous voulez mon raisonnement: 1)% s nécessite 2 caractères supplémentaires par espace réservé vs + oblige minimum de 4 (ou 8 si vous suivez PEP8, 13 si vous forcez), 2)% s est enfermé dans une seule chaîne, il est donc plus facile d'analyser visuellement, avec +, vous avez plus de pièces en mouvement: chaîne proche, opérateur, variable , opérateur, chaîne ouverte, 3) coloration de la syntaxe% s a une couleur pour chaque fonction: chaîne et espace réservé, avec + vous obtenez trois couleurs: chaîne, opérateur et couleur variable.
Lie Ryan
4
@ L.Möller: 4) J'ai la possibilité de mettre des chaînes de format plus longues dans une variable ou un dictionnaire, là où le formatage doit être effectué, 5) la chaîne de format peut être spécifiée par l'utilisateur à partir d'un fichier de configuration, des arguments de commande ou d'une base de données. , on ne peut pas en dire autant des concaténations. Mais oui, je n’utiliserais pas non plus% s lorsque j’ai plus de 4 à 5 choses à interpoler, mais plutôt la variante de% (varname) s ou "{foo}". Format () en Python. Je pense que les noms explicites améliorent la lisibilité pour les chaînes de format plus longues avec beaucoup de variables interpolées.
Lie Ryan
2
Je ne sais pas ce qui est "vrai", c'est pourquoi je vous demande si vous avez des preuves :-). Vraiment d'accord avec votre deuxième commentaire
Lovis
6
Je trouve le n ° 2 suspect - avez-vous une preuve documentée? Je ne connais pas très bien Java, mais en C #, la concaténation est plus rapide que l’interpolation de chaînes . Je suis tout à fait d’accord avec # 1 et je m’appuie vraiment sur cela pour décider quand utiliser lequel, mais vous devez vous rappeler que l’interpolation nécessite une certaine quantité d’analyses de chaînes et une complexité où la concaténation n’exige rien de tout cela.
Jimmy Hoffa
48

Suis-je le seul qui lit de gauche à droite?

Pour moi, utiliser, %sc'est comme écouter des locuteurs allemands, où je dois attendre la fin d'une très longue phrase pour entendre le verbe.

Laquelle de celles-ci est plus claire en un coup d'œil?

"your %s is in the %s" % (object, location)

ou

"your " + object + " is in the " + location  
Mawg
la source
17
Évidemment, ceci est subjectif, car je trouve le premier plus lisible - et plus facile à écrire et à éditer. La seconde mélange le texte avec du code qui les obscurcit et ajoute du bruit. Par exemple, il est facile de se tromper d'espaces dans la seconde.
JacquesB
5
@JacquesB Je pense en fait que votre cerveau est si familier avec ce format que vous sautez immédiatement entre les crochets et que vous remplacez les mots instantanément. Techniquement, ce n'est pas une lecture de gauche à droite, mais c'est parfaitement correct. Je trouve que je le fais aussi, alors oui, 1 est plus facile à lire parce que je sais que je dois faire face à des problèmes d'espacement stupides avant et après les guillemets dans la seconde, et c'est vraiment lent à travailler.
Nelson
3
Après des ndécennies, mon esprit fonctionne aussi de cette façon ;-) Mais je maintiens toujours ma réponse, la seconde est plus claire et plus facile à lire, donc à maintenir. Et cela devient plus évident avec le plus de paramètres que vous avez. En fin de compte, s'il s'agit d'un one man show, optez pour ce que vous connaissez et avec lequel vous êtes à l'aise; s'il s'agit d'un effort d'équipe, appliquez la cohérence et les révisions de code; les gens peuvent s'y habituer.
Mawg
4
Le premier est beaucoup plus lisible pour moi car il a moins de "cruel" au milieu de la phrase. Il est plus facile pour mon regard de regarder à la fin que pour mon cerveau d’analyser les guillemets, espaces et avantages supplémentaires. Bien sûr, je préfère maintenant beaucoup les chaînes de format Python 3.6: f"your {object} is in the {location}".
Dustin Wyatt
8
Je trouve également encore plus difficile de lire et d’écrire lorsque la variable doit être entourée de guillemets. "your '" + object + "' is in the '" + location + "'"... Je ne suis même pas sûr d'avoir tout compris tout à l'heure ...
Dustin Wyatt
12

Un exemple expliquant l'argument de lisibilité:

print 'id: ' + id + '; function: ' + function + '; method: ' + method + '; class: ' + class + ' -- total == ' + total

print 'id: %s; function: %s; method: %s; class: %s --total == %s' % \
   (id, function, method, class, total)

(Notez que le deuxième exemple est non seulement plus lisible mais aussi plus facile à modifier, vous pouvez changer le modèle sur une ligne et la liste des variables sur une autre)

Un problème distinct est que le code% s est également converti en chaîne, sinon vous devez utiliser l'appel str (), qui est également moins lisible qu'un code% s.

Pluvieux
la source
1
Je ne suis pas d'accord avec votre première déclaration, mais nous pouvons accepter de différer. J'étais sur le point de poster une réponse dans le sens de votre seconde, alors votez
Mawg
6

L'utilisation ne+ doit pas être évitée en général. Dans de nombreux cas, c'est la bonne approche. Utiliser %sou .join()ne sont préférables que dans des cas particuliers, et il est généralement tout à fait évident que ce soit la meilleure solution.

Dans votre exemple, vous concaténez trois chaînes, et l'exemple que vous utilisez +est clairement le plus simple et le plus lisible, et par conséquent le recommandé.

%sou .format()sont utiles si vous souhaitez interpoler des chaînes ou des valeurs au milieu d'une chaîne plus grande. Exemple:

print "Hello %s, welcome to the computer!" % name

Dans ce cas, son utilisation %sest plus lisible car vous évitez de couper la première chaîne en plusieurs segments. Surtout si vous interpolez plusieurs valeurs.

.join() est approprié si vous avez une séquence de chaînes de taille variable et / ou si vous souhaitez concaténer plusieurs chaînes avec le même séparateur.

JacquesB
la source
2

Étant donné que l'ordre des mots peut changer dans différentes langues, il %sest impératif d'utiliser un formulaire si vous souhaitez prendre en charge correctement la traduction des chaînes dans votre logiciel.

martjno
la source