with - python list to string




Python join: pourquoi est-ce string.join(list) au lieu de list.join(string)? (6)

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

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 spécifique à cela?


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

C'est parce que join est une méthode "string"! 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 de quand nous avons des itérations qui ne sont pas des listes?

Que faire si vous avez un tuple de chaînes? S'il s'agissait d'une méthode de list , vous auriez à lancer tous les itérateurs de chaînes comme une list avant de pouvoir joindre les éléments en une seule chaîne! Par exemple:

some_strings = ('foo', 'bar', 'baz')

Lançons notre propre méthode de jointure de liste:

class OurList(list): 
    def join(self, s):
        return s.join(self)

Et pour l'utiliser, notez que nous devons d'abord créer une liste de chaque itérable pour joindre les chaînes dans ce itérable, gaspillant à la fois la mémoire et la puissance de traitement:

>>> l = OurList(some_strings) # step 1, create our list
>>> l.join(', ') # step 2, use our list join method!
'foo, bar, baz'

Nous voyons donc que nous devons ajouter une étape supplémentaire pour utiliser notre méthode de liste, au lieu de simplement utiliser la méthode de chaîne intégrée:

>>> ' | '.join(some_strings) # a single step!
'foo | bar | baz'

Avertissement de performance pour les générateurs

L'algorithme utilisé par Python pour créer la chaîne finale avec str.join doit effectivement passer deux fois sur l'itérateur, donc si vous lui fournissez une expression de générateur, il doit la matérialiser dans une liste avant de pouvoir créer la chaîne finale.

Ainsi, tout en str.join autour des générateurs est généralement meilleur que la compréhension des listes, str.join est une exception:

>>> import timeit
>>> min(timeit.repeat(lambda: ''.join(str(i) for i in range(10) if i)))
3.839168446022086
>>> min(timeit.repeat(lambda: ''.join([str(i) for i in range(10) if i])))
3.339879313018173

Néanmoins, l'opération str.join est toujours sémantiquement une opération "chaîne", donc il est toujours logique de l'avoir sur l'objet str par rapport aux itérations diverses.


C'est parce que tout itérable peut être joint, pas seulement les listes, mais le résultat et le "menuisier" sont toujours des chaînes.

PAR EXEMPLE:

import urllib2
print '\n############\n'.join(
    urllib2.urlopen('http://data.stackexchange.com/users/7095'))

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 doit aussi fonctionner pour différentes itérations (tuples, générateurs, etc.)
  • il doit avoir un comportement différent entre différents types de chaînes.

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 il devrait inspecter ses arguments pour décider lequel d'entre eux appeler. Et vous ne pouvez pas joindre les octets et les str, alors la façon dont ils l'ont maintenant est logique.


Parce que la méthode join() est dans la classe de chaîne, au lieu de la classe de liste?

Je suis d'accord, ça a l'air marrant.

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

Note historique Quand j'ai appris Python pour la première fois, je m'attendais à ce que join soit une méthode d'une liste, qui prendrait le délimiteur comme argument. Beaucoup de gens ressentent la même chose, et il y a une histoire derrière la méthode join. Avant Python 1.6, les chaînes n'avaient pas toutes ces méthodes utiles. Il y avait un module de chaîne séparé qui contenait toutes les fonctions de chaîne; chaque fonction a pris une chaîne comme premier argument. Les fonctions ont été jugées suffisamment importantes pour être mises sur les cordes elles-mêmes, ce qui a du sens pour les fonctions comme le bas, le haut et le split. Mais de nombreux programmeurs Python se sont opposés à la nouvelle méthode de jointure, arguant qu'elle devrait plutôt être une méthode de la liste, ou qu'elle ne devrait pas bouger du tout mais rester simplement une partie de l'ancien module de chaîne (qui a encore beaucoup à faire de choses utiles dedans). J'utilise la nouvelle méthode de jointure exclusivement, mais vous verrez le code écrit dans les deux sens, et si cela vous dérange vraiment, vous pouvez utiliser l'ancienne fonction string.join à la place.

--- Mark Pilgrim, Plongez dans Python


Principalement parce que le résultat d'un someString.join() est une chaîne.

La séquence (list 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 comme une méthode d'une chaîne.


- déclarez que vous vous joignez à une liste et convertissez en une chaîne.Il est axé sur les résultats (juste pour la mémoire et la compréhension)

Je fais un cheatsheet exhaustif de methods_of_string pour votre référence.

string_methonds_44 = {
    'convert': ['join','split', 'rsplit','splitlines', 'partition', 'rpartition'],
    'edit': ['replace', 'lstrip', 'rstrip', 'strip'],
    'search': ['endswith', 'startswith', 'count', 'index', 'find','rindex', 'rfind',],
    'condition': ['isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isnumeric','isidentifier',
                  'islower','istitle', 'isupper','isprintable', 'isspace', ],
    'text': ['lower', 'upper', 'capitalize', 'title', 'swapcase',
             'center', 'ljust', 'rjust', 'zfill', 'expandtabs','casefold'],
    'encode': ['translate', 'maketrans', 'encode'],
    'format': ['format', 'format_map']}




join