Cela m'a toujours dérouté. Il semble que ce serait mieux:
my_list = ["Hello", "world"]
print(my_list.join("-"))
# Produce: "Hello-world"
Que ceci:
my_list = ["Hello", "world"]
print("-".join(my_list))
# Produce: "Hello-world"
Y a-t-il une raison précise à cela?
-
déclare que vous joignez une liste et que vous la convertissez en chaîne. Elle est orientée vers les résultats.str
que de l'implémenter sur chaque type itérable.Réponses:
C'est parce que tout itérable peut être joint (par exemple, list, tuple, dict, set), mais le résultat et le "joiner" doivent être des chaînes.
Par exemple:
Utiliser autre chose que des chaînes générera l'erreur suivante:
la source
list.join(string)
semble plus une approche orientée objet alors qu'ellestring.join(list)
me semble beaucoup plus procédurale.print(str.join('-', my_list))
et ça marche, ça se sent mieux.__iter__
méthode. Exiger que tous les itérables soient également implémentésjoin
compliquerait une interface générale (qui couvre également les itérables sur des non-chaînes) pour un cas d'utilisation très particulier. La définitionjoin
sur les strins des étapes secondaires de ce problème au détriment de la commande "non intuitive". Un meilleur choix aurait pu être de le garder une fonction avec le premier argument étant l'itérable et le second (optionnel) étant la chaîne de menuisier - mais ce navire a navigué.Cela a été discuté dans les méthodes String ... enfin enfiler dans le Python-Dev achive, et a été accepté par Guido. Ce fil a commencé en juin 1999 et a
str.join
été inclus dans Python 1.6 qui a été publié en septembre 2000 (et pris en charge Unicode). Python 2.0 (str
méthodes prises en charge inclusesjoin
) a été publié en octobre 2000.str.join(seq)
seq.join(str)
seq.reduce(str)
join
comme fonction intégréelist
s,tuple
s, 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. Donc, utiliser un espace de noms intégré n'est pas bon. Sijoin()
prend en charge de nombreux types de données, la création d'une implémentation optimisée serait difficile, si elle est implémentée à l'aide de la__add__
méthode, alors c'est O (n²).sep
) ne doit pas être omise. Explicite vaut mieux qu'implicite.Il n'y a pas d'autres raisons proposées dans ce fil.
Voici quelques réflexions supplémentaires (les miennes et celles de mes amis):
La décision de Guido est enregistrée dans un courrier historique , décidant
str.join(seq)
:la source
Parce que la
join()
méthode est dans la classe de chaîne, au lieu de la classe de liste?Je suis d'accord, ça a l'air drôle.
Voir http://www.faqs.org/docs/diveintopython/odbchelper_join.html :
la source
string
bibliothèque Python 3 a supprimé toutes lesstr
méthodes redondantes , vous ne pouvez donc plus les utiliserstring.join()
. Personnellement, je n'ai jamais pensé que c'était «drôle», c'est parfaitement logique, car vous pouvez rejoindre bien plus que de simples listes, mais le menuisier est toujours une chaîne!Je suis d'accord 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 car:
Il existe en fait deux méthodes de jointure (Python 3.0):
Si join était une méthode d'une liste, alors il devrait inspecter ses arguments pour décider lequel appeler. Et vous ne pouvez pas joindre octet et str ensemble, donc la façon dont ils l'ont maintenant a du sens.
la source
C'est parce que
join
c'est une méthode "chaîne"! Il crée une chaîne à partir de n'importe quel itérable. Si nous avons collé la méthode sur des listes, qu'en est-il lorsque nous avons des itérables qui ne sont pas des listes?Et si vous avez un tuple de cordes? S'il s'agissait d'une
list
méthode, vous devriezlist
convertir chaque itérateur de chaînes en un avant de pouvoir joindre les éléments en une seule chaîne! Par exemple:Lançons notre propre méthode de jointure de liste:
Et pour l'utiliser, notez que nous devons d'abord créer une liste à partir de chaque itérable pour joindre les chaînes dans cet itérable, gaspillant à la fois de la mémoire et de la puissance de traitement:
Nous voyons donc que nous devons ajouter une étape supplémentaire pour utiliser notre méthode de liste, au lieu d'utiliser simplement la méthode de chaîne intégrée:
Avertissement de performance pour les générateurs
L'algorithme utilisé par Python pour créer la chaîne finale
str.join
doit en fait passer deux fois sur l'itérable, donc si vous lui fournissez une expression de générateur, il doit d'abord le matérialiser dans une liste avant de pouvoir créer la chaîne finale.Ainsi, bien que le fait de contourner les générateurs soit généralement meilleur que les compréhensions de liste, il
str.join
s'agit d'une exception:Néanmoins, l'
str.join
opération est toujours sémantiquement une opération "chaîne", il est donc logique de l'avoir sur l'str
objet que sur divers itérables.la source
Considérez-le comme l'opération orthogonale naturelle à diviser.
Je comprends pourquoi il s'applique à tout ce qui est itérable et ne peut donc pas être facilement mis en œuvre simplement sur la liste.
Pour plus de lisibilité, j'aimerais le voir dans le langage, mais je ne pense pas que ce soit réellement faisable - si l'itérabilité était une interface, elle pourrait être ajoutée à l'interface, mais ce n'est qu'une convention et il n'y a donc pas de moyen central de ajoutez-le à l'ensemble des choses qui sont itérables.
la source
Principalement parce que le résultat d'un
someString.join()
est une chaîne.La séquence (liste ou tuple ou autre) n'apparaît pas dans le résultat, juste une chaîne. Parce que le résultat est une chaîne, il est logique en tant que méthode d'une chaîne.
la source
-
in "-". join (my_list) déclare que vous êtes en train de convertir une chaîne en joignant des éléments à une liste. Elle est orientée résultats. (juste pour une mémoire et une compréhension faciles)Je fais une feuille de triche exhaustive de methods_of_string pour votre référence.
la source
Les deux ne sont pas gentils.
string.join (xs, delimit) signifie que le module de chaîne est au courant de l'existence d'une liste, qu'il n'a aucune raison de connaître, car le module de chaîne ne fonctionne qu'avec des chaînes.
list.join (delimit) est un peu plus agréable car nous sommes tellement habitués à ce que les chaînes soient un type fondamental (et linguistiquement, elles le sont). Cependant, cela signifie que la jointure doit être distribuée de manière dynamique car dans le contexte arbitraire du
a.split("\n")
compilateur python, il se peut que vous ne sachiez pas ce qu'est un fichier, et devrez le rechercher (de manière analogue à la recherche vtable), ce qui est coûteux si vous le faites beaucoup de fois.si le compilateur d'exécution python sait que la liste est un module intégré, il peut ignorer la recherche dynamique et encoder l'intention directement dans le bytecode, alors qu'autrement il doit résoudre dynamiquement la "jointure" de "a", qui peut être composée de plusieurs couches d'héritage par appel (car entre les appels, la signification de join peut avoir changé, car python est un langage dynamique).
malheureusement, c'est le défaut ultime de l'abstraction; peu importe l'abstraction que vous choisissez, votre abstraction n'aura de sens que dans le contexte du problème que vous essayez de résoudre, et en tant que tel, vous ne pourrez jamais avoir une abstraction cohérente qui ne devienne pas incompatible avec les idéologies sous-jacentes lorsque vous commencez à les coller. ensemble sans les envelopper dans une vue conforme à votre idéologie. Sachant cela, l'approche de python est plus flexible car c'est moins cher, c'est à vous de payer plus pour le rendre "plus joli", soit en créant votre propre wrapper, soit votre propre préprocesseur.
la source
Les variables
my_list
et"-"
sont les deux objets. Plus précisément, ce sont des instances des classeslist
etstr
, respectivement. Lajoin
fonction appartient à la classestr
. Par conséquent, la syntaxe"-".join(my_list)
est utilisée car l'objet"-"
prendmy_list
en entrée.la source