web-dev-qa-db-fra.com

Python .join ou concaténation de chaînes

Je me rends compte que si vous avez un itérable, vous devez toujours utiliser .join(iterable) au lieu de for x in y: str += x. Mais s'il n'y a qu'un nombre fixe de variables qui ne sont pas déjà dans un itérable, l'utilisation de .join() est-elle toujours la méthode recommandée?

Par exemple, j'ai

user = 'username'
Host = 'Host'

devrais-je

ret = user + '@' + Host

ou

ret = '@'.join([user, Host])

Je ne demande pas tant du point de vue des performances, car les deux seront assez triviaux. Mais j'ai lu que les gens ici disent toujours utiliser .join() et je me demandais s'il y avait une raison particulière à cela ou si c'était généralement une bonne idée d'utiliser .join().

24
Falmarri

Si vous créez une chaîne comme celle-ci, vous souhaitez normalement utiliser la mise en forme des chaînes:

>>> user = 'username'
>>> Host = 'Host'
>>> '%s@%s' % (user, Host)
'username@Host'

Python 2.6 a ajouté un autre formulaire, qui ne repose pas sur la surcharge de l'opérateur et a quelques fonctionnalités supplémentaires:

>>> '{0}@{1}'.format(user, Host)
'username@Host'

En règle générale, la plupart des gens n'utiliseront + Sur les chaînes que s'ils y ajoutent deux chaînes. Pour plus de parties ou de chaînes plus complexes, ils utilisent soit le formatage de chaînes, comme ci-dessus, soit assemblent des éléments dans une liste et les joignent ensemble (surtout s'il y a une forme de boucle impliquée.) La raison d'utiliser str.join() est que l'ajout de chaînes signifie créer une nouvelle chaîne (et potentiellement détruire les anciennes) pour chaque ajout. Python peut parfois optimiser cela, mais str.join() devient rapidement plus clair, plus évident et beaucoup plus rapide.

29
Thomas Wouters

Je prends la question pour signifier: "Est-ce correct de faire ceci:"

ret = user + '@' + Host

..Et la réponse est oui. C'est parfaitement bien.

Vous devez, bien sûr, être conscient des trucs sympas de mise en forme que vous pouvez faire en Python, et vous devez être conscient que pour les longues listes, "rejoindre" est le chemin à parcourir, mais pour une situation simple comme celle-ci, ce que vous avez est exactement à droite. C'est simple et clair, et les performances ne seront pas un problème.

14
Nick Perkins

(Je suis à peu près sûr que toutes les personnes pointant sur le formatage des chaînes manquent complètement la question.)

La création d'une chaîne en construisant un tableau et en le joignant est uniquement pour des raisons de performances. À moins que vous n'ayez besoin de cette performance, ou à moins que cela ne soit de toute façon le moyen naturel de l'implémenter, cela ne présente aucun avantage plutôt qu'une simple concaténation de chaînes.

Dire '@'.join([user, Host]) n'est pas intuitif. Cela me fait me demander: pourquoi fait-il cela? Y a-t-il des subtilités? y a-t-il des cas où il pourrait y avoir plus d'un "@"? La réponse est non, bien sûr, mais il faut plus de temps pour arriver à cette conclusion que si elle avait été écrite de manière naturelle.

Ne déformez pas votre code simplement pour éviter la concaténation de chaînes; il n'y a rien de fondamentalement mauvais avec ça. Rejoindre des tableaux n'est qu'une optimisation.

10
Glenn Maynard

Je noterai simplement que j'ai toujours eu tendance à utiliser la concaténation sur place jusqu'à ce que je relise une partie du style général Python PEP Guide de style PEP-8 pour le code Python .

  • Le code doit être écrit d'une manière qui ne désavantage pas les autres implémentations de Python (PyPy, Jython, IronPython, Pyrex, Psyco, etc.). Par exemple, ne vous fiez pas à l'implémentation efficace de CPython de la concaténation de chaînes sur place pour les instructions sous la forme a + = b ou a = a + b. Ces instructions s'exécutent plus lentement dans Jython. Dans les parties sensibles aux performances de la bibliothèque, le formulaire '' .join () doit être utilisé à la place. Cela garantira que la concaténation se produit en temps linéaire sur différentes implémentations.

En passant par cela, je me suis converti à la pratique de l'utilisation des jointures afin que je puisse conserver l'habitude comme une pratique plus automatique lorsque l'efficacité est extrêmement critique.

Je vais donc mettre mon vote pour:

ret = '@'.join([user, Host])
8
Matthew

J'utilise ensuite:

ret = '%s@%s' % (user, Host)
1
anti_social

Je recommande join() plutôt que la concaténation, basée sur deux aspects:

  1. Plus rapide.
  2. Plus élégant.

Concernant le premier aspect, voici un exemple:

import timeit    

s1 = "Flowers"    
s2 = "of"    
s3 = "War"    

def join_concat():    
    return s1 + " " + s2 + " " + s3  

def join_builtin():    
    return " ".join((s1, s2, s3))    

print("Join Concatenation: ", timeit.timeit(join_concat))         
print("Join Builtin:       ", timeit.timeit(join_builtin))

Le résultat:

$ python3 join_test.py
Join Concatenation:  0.40386943198973313
Join Builtin:        0.2666833929979475

Compte tenu d'un énorme ensemble de données (millions de lignes) et de son traitement, 130 millisecondes par ligne, c'est trop.

Et pour le deuxième aspect, en effet, il est plus élégant.

0
ivanleoncz