Quel est l'intérêt de '/segment/segment/'.split('/')
renvoyer ['', 'segment', 'segment', '']
?
Remarquez les éléments vides. Si vous vous divisez sur un délimiteur qui se trouve être à la position un et à la toute fin d'une chaîne, quelle valeur supplémentaire vous donne-t-il pour que la chaîne vide soit renvoyée de chaque extrémité?
str.split
Complète str.join
, Donc
"/".join(['', 'segment', 'segment', ''])
vous récupère la chaîne d'origine.
Si les chaînes vides n'étaient pas là, le premier et le dernier '/'
Seraient manquants après la join()
Plus généralement, pour supprimer les chaînes vides renvoyées dans les résultats split()
, vous souhaiterez peut-être consulter la fonction filter
.
Exemple:
filter(None, '/segment/segment/'.split('/'))
résultats
['segment', 'segment']
Il y a deux points principaux à considérer ici:
'/segment/segment/'.split('/')
soit égal à ['segment', 'segment']
Est raisonnable, mais cela perd des informations. Si split()
a fonctionné comme vous le vouliez, si je vous dis que a.split('/') == ['segment', 'segment']
, vous ne pouvez pas me dire ce qu'était a
.'a//b'.split()
? ['a', 'b']
?, Ou ['a', '', 'b']
? C'est-à-dire, split()
doit-il fusionner les délimiteurs adjacents? Si c'est le cas, il sera très difficile d'analyser les données délimitées par un caractère et certains des champs peuvent être vides. Je suis assez sûr qu'il y a beaucoup de gens qui font veulent les valeurs vides dans le résultat pour le cas ci-dessus!Au final, cela se résume à deux choses:
Cohérence: si j'ai des délimiteurs n
, dans a
, je récupère les valeurs de n+1
Après le split()
.
Il devrait être possible de faire des choses complexes et faciles à faire des choses simples: si vous voulez ignorer les chaînes vides à la suite de split()
, vous pouvez toujours faire:
def mysplit(s, delim=None):
return [x for x in s.split(delim) if x]
mais si l'on ne veut pas ignorer les valeurs vides, on devrait pouvoir.
Le langage doit choisir une définition de split()
- il y a trop de cas d'utilisation différents pour satisfaire aux exigences de chacun par défaut. Je pense que le choix de Python est bon et le plus logique. (En passant, l'une des raisons pour lesquelles je n'aime pas le strtok()
de C est qu'il fusionne les délimiteurs adjacents, ce qui rend extrêmement difficile d'effectuer une analyse/tokenisation sérieuse avec lui.)
Il y a une exception: a.split()
sans argument serre l'espace blanc consécutif, mais on peut affirmer que c'est la bonne chose à faire dans ce cas. Si vous ne voulez pas le comportement, vous pouvez toujours a.split(' ')
.
Avoir x.split(y)
toujours renvoyer une liste d'éléments 1 + x.count(y)
est une régularité précieuse - comme @ gnibbler l'a déjà souligné, cela fait split
et join
des inverses exacts les uns des autres (comme ils devraient évidemment l'être), il mappe également avec précision la sémantique de toutes sortes d'enregistrements joints par un délimiteur (tels que csv
lignes de fichier [[net de problèmes de citation]], lignes de /etc/group
Sous Unix, etc.), il permet (comme la réponse de @ Roman l'a mentionné) de vérifier facilement (par exemple) les chemins absolus et relatifs (dans les chemins de fichiers et les URL), etc.
Une autre façon de voir les choses est que vous ne devriez pas jeter des informations par la fenêtre sans aucun gain. Que gagnerait-on à rendre x.split(y)
équivalent à x.strip(y).split(y)
? Rien, bien sûr - il est facile d'utiliser le deuxième formulaire lorsque c'est ce que vous voulez dire, mais si le premier formulaire était arbitrairement réputé signifier le second, vous auriez beaucoup de travail à faire lorsque vous faites veut le premier (ce qui est loin d'être rare, comme le souligne le paragraphe précédent).
Mais vraiment, penser en termes de régularité mathématique est la façon la plus simple et la plus générale de vous apprendre à concevoir des API passables. Pour prendre un exemple différent, il est très important que pour tout x
et y
x == x[:y] + x[y:]
Valide - ce qui indique immédiatement pourquoi un extrême d'une tranche devrait être exclu. Plus l'assertion invariante est simple à formuler, plus il est probable que la sémantique qui en résulte est ce dont vous avez besoin dans la vie réelle - une partie du fait mystique que les mathématiques sont très utiles dans le traitement de l'univers.
Essayez de formuler l'invariant pour un dialecte split
dans lequel les délimiteurs de début et de fin sont placés dans un cas spécial ... contre-exemple: les méthodes de chaîne telles que isspace
ne sont pas simples au maximum - x.isspace()
équivaut à x and all(c in string.whitespace for c in x)
- ce stupide début x and
est la raison pour laquelle vous vous retrouvez si souvent à coder not x or x.isspace()
, pour revenir à la simplicité qui should ont été conçus dans les méthodes de chaîne is...
(où une chaîne vide "est" tout ce que vous voulez - contrairement au sens du cheval de l'homme de la rue, peut-être [[vide les ensembles, comme zéro et c, ont toujours dérouté la plupart des gens ;-)]], mais se conforment pleinement à un bon sens évident mathématique de bon sens! -).
Je ne sais pas quel type de réponse vous cherchez? Vous obtenez trois correspondances car vous avez trois délimiteurs. Si vous ne voulez pas que celui-ci soit vide, utilisez simplement:
'/segment/segment/'.strip('/').split('/')
Eh bien, cela vous permet de savoir qu'il y avait un délimiteur là-bas. Donc, voir 4 résultats vous permet de savoir que vous aviez 3 délimiteurs. Cela vous donne le pouvoir de faire tout ce que vous voulez avec ces informations, plutôt que d'avoir Python supprimer les éléments vides, puis vous faire vérifier manuellement le début ou la fin des délimiteurs si vous avez besoin de le savoir.
Exemple simple: supposons que vous vouliez vérifier les noms de fichiers absolus et relatifs. De cette façon, vous pouvez tout faire avec le fractionnement, sans avoir à vérifier également le premier caractère de votre nom de fichier.