2085 votes

Pourquoi est-ce string.join(list) au lieu de list.join(string) ?

Cela m'a toujours dérouté. Il semble que ce serait plus agréable :

["Hello", "world"].join("-")

Que ça :

"-".join(["Hello", "world"])

Y a-t-il une raison spécifique pour laquelle il est comme ça ?

5 votes

Pour une mémorisation et une compréhension faciles, - déclare que vous joignez une liste et que vous la convertissez en chaîne de caractères.

25 votes

@JawSaw : Ça ne fait qu'embrouiller davantage mem.

8 votes

Je pense que l'idée originale est que, puisque join() retourne une chaîne de caractères, il devrait être appelé depuis le contexte de la chaîne de caractères. Mettre join() sur une liste n'a pas beaucoup de sens dans la mesure où une liste est un conteneur d'objets et ne devrait pas avoir une fonction unique spécifique aux chaînes de caractères.

1432voto

recursive Points 34729

C'est parce que n'importe quel itérable peut être joint (par exemple, une liste, un tuple, un dict, un ensemble), mais son contenu et le "joiner". doit être ficelles.

Par exemple :

'_'.join(['welcome', 'to', 'stack', 'overflow'])
'_'.join(('welcome', 'to', 'stack', 'overflow'))

'welcome_to_stack_overflow'

Si vous utilisez autre chose que des chaînes de caractères, vous obtiendrez l'erreur suivante :

TypeError : élément de séquence 0 : attendu str instance, int found

111 votes

Je ne suis pas d'accord sur le plan conceptuel, même si cela a du sens sur le plan du code. list.join(string) apparaît davantage comme une approche orientée objet alors que string.join(list) me semble beaucoup plus procédurale.

45 votes

Alors pourquoi n'est-il pas implémenté sur les itérables ?

19 votes

@TimeSheep : Une liste d'entiers n'a pas de jointure significative, même si elle est itérable.

446voto

Yoshiki Shibukawa Points 561

Ce point a été discuté dans le Méthodes String... enfin dans le fil de discussion Python-Dev, et a été accepté par Guido. Ce fil de discussion a commencé en juin 1999, et str.join était inclus dans Python 1.6 qui a été publié en septembre 2000 (et supportait Unicode). Python 2.0 (supportant str méthodes comprenant join ) a été publié en octobre 2000.

  • Quatre options ont été proposées dans ce fil de discussion :
    • str.join(seq)
    • seq.join(str)
    • seq.reduce(str)
    • join comme une fonction intégrée
  • Guido voulait soutenir non seulement list et tuple mais toutes les séquences/itérables.
  • seq.reduce(str) est difficile pour les nouveaux arrivants.
  • seq.join(str) introduit une dépendance inattendue des séquences vers str/unicode.
  • join() en tant que fonction intégrée ne prendrait en charge que des types de données spécifiques. L'utilisation d'un espace de noms intégré n'est donc pas une bonne chose. Si join() supporte de nombreux types de données, la création d'une implémentation optimisée serait difficile, si elle est mise en œuvre à l'aide de l'outil de gestion des données. __add__ alors il aurait O(n²) .
  • La chaîne de séparation ( sep ) ne doit pas être omise. L'explicite est préférable à l'implicite.

Voici quelques réflexions supplémentaires (les miennes et celles de mon ami) :

  • La prise en charge d'Unicode était prévue, mais elle n'était pas définitive. À cette époque, UTF-8 était le plus susceptible de remplacer UCS2/4. Pour calculer la longueur totale du tampon des chaînes UTF-8, il faut connaître la règle de codage des caractères.
  • À l'époque, Python avait déjà décidé d'une règle commune d'interface de séquence où un utilisateur pouvait créer une classe de type séquence (itérable). Mais Python n'a pas supporté l'extension des types intégrés avant la version 2.2. À cette époque, il était difficile de fournir des iterable (qui est mentionné dans un autre commentaire).

La décision de Guido est enregistrée dans un courrier historique en décidant de str.join(seq) :

C'est drôle, mais ça semble juste ! Barry, vas-y...
Guido van Rossum

255voto

Bill Karwin Points 204877

Parce que le join() est dans la classe string, au lieu de la classe list ?

Je suis d'accord, ça a l'air drôle.

Ver http://www.faqs.org/docs/diveintopython/odbchelper_join.html :

Note historique. Lorsque j'ai appris pour la première fois Python, je m'attendais à ce que join soit une méthode d'une liste, qui prendrait le comme argument. Beaucoup de de personnes pensent la même chose, et il y a une une histoire derrière la méthode join. Précédent Python 1.6, les chaînes ne disposaient pas de toutes ces méthodes utiles. Il y avait un module string séparé qui contenait toutes les fonctions de chaînes de caractères ; chaque fonction prenait une chaîne comme premier argument. Ces fonctions ont été jugées suffisamment importantes pour être placées sur les chaînes de caractères elles-mêmes, ce qui était logique pour des fonctions comme lower, upper, et split. Mais beaucoup d'irréductibles Python se sont opposés à la nouvelle méthode de jointure en faisant valoir qu'elle devrait être une méthode méthode de la liste à la place, ou qu'elle ne devrait pas se déplacer du tout mais simplement rester partie de l'ancien module string (qui qui contient encore beaucoup de choses utiles). J'utilise exclusivement la nouvelle méthode join, mais vous verrez du code écrit soit façon, et si cela vous dérange vraiment, vous pouvez pouvez utiliser l'ancienne fonction string.join à la place.

--- Mark Pilgrim, Dive into Python (plonger dans Python)

15 votes

Le Python 3 string La bibliothèque a supprimé tous les éléments redondants str de sorte que vous ne pouvez plus utiliser string.join() . Personnellement, je n'ai jamais trouvé cela "drôle", c'est tout à fait logique, car vous pouvez joindre beaucoup plus que des listes, mais celui qui joint est toujours une chaîne !

80voto

Kiv Points 9116

Je reconnais que c'est contre-intuitif au début, mais il y a une bonne raison. Join ne peut pas être une méthode d'une liste parce que :

  • cela doit aussi fonctionner pour des itérables différents (tuples, générateurs, etc.)
  • il doit avoir un comportement différent entre les différents types de chaînes de caractères.

Il existe en fait deux méthodes de jointure (Python 3.0) :

>>> b"".join
<built-in method join of bytes object at 0x00A46800>
>>> "".join
<built-in method join of str object at 0x00A28D40>

Si join était une méthode d'une liste, alors elle devrait inspecter ses arguments pour décider lequel d'entre eux appeler. Et vous ne pouvez pas joindre un octet et une chaîne de caractères ensemble, donc la façon dont ils le font maintenant est logique.

25voto

Andy Dent Points 9852

Considérez-le comme l'opération orthogonale naturelle à la division.

Je comprends pourquoi il est applicable à tout ce qui est itérable et ne peut donc pas être facilement implémenté juste sur la liste.

Si l'itérabilité était une interface, elle pourrait être ajoutée à l'interface, mais il ne s'agit que d'une convention et il n'y a donc pas de moyen central de l'ajouter à l'ensemble des choses qui sont itérables.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X