Formation Python
Parfois, vous devez traiter des listes Python en partant du dernier élément jusqu'au premier, en d'autres termes, dans ordre inverse. En général, il existe deux principaux défis liés au travail avec des listes à l'envers :
Pour relever le premier défi, vous pouvez utiliser soit .sens inverse()
ou une boucle qui échange les éléments par index. Pour la seconde, vous pouvez utiliser renversé()
ou une opération de tranchage. Dans les sections suivantes, vous découvrirez différentes manières d'accomplir les deux dans votre code.
Inverser les listes en place
Comme d'autres types de séquences mutables, les listes Python implémentent .sens inverse()
. Cette méthode inverse la liste sous-jacente en place pour une efficacité de mémoire lorsque vous inversez des objets de liste volumineux. Voici comment vous pouvez utiliser .sens inverse()
:
>>> chiffres = [[[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> chiffres.sens inverse()
>>> chiffres
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Quand vous appelez .sens inverse()
sur une liste existante, la méthode l'inverse en place. De cette façon, lorsque vous accédez à nouveau à la liste, vous l'obtenez dans l'ordre inverse. Noter que .sens inverse()
ne renvoie pas une nouvelle liste mais Rien
:
>>> chiffres = [[[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> chiffres_inversés = chiffres.sens inverse()
>>> chiffres_inversés est Rien
Vrai
Essayer d'attribuer la valeur de retour de .sens inverse()
à une variable est une erreur courante liée à l'utilisation de cette méthode. L'intention de revenir Rien
est de rappeler à ses utilisateurs que .sens inverse()
fonctionne par effet secondaire, en changeant la liste sous-jacente.
Noter: La plupart des exemples de ce didacticiel utilisent une liste de nombres en entrée. Cependant, les mêmes outils et techniques s'appliquent aux listes de tout type d'objets Python, telles que les listes de chaînes.
D'accord! C'était simple et rapide ! Maintenant, comment pouvez-vous inverser une liste en place à la main ? Une technique courante consiste à parcourir la première moitié de celui-ci tout en échangeant chaque élément avec son homologue miroir sur la seconde moitié de la liste.
Python fournit des indices positifs de base zéro pour parcourir les séquences de gauche à droite. Il permet également de naviguer dans les séquences de droite à gauche à l'aide d'indices négatifs :
Ce schéma montre que vous pouvez accéder au premier élément de la liste (ou séquence) en utilisant soit 0
ou alors -5
avec l'opérateur d'indexation, comme dans séquence[0]
et séquence[-5]
, respectivement. Vous pouvez utiliser cette fonctionnalité Python pour inverser la séquence sous-jacente en place.
Par exemple, pour inverser la liste représentée dans le diagramme, vous pouvez boucler sur la première moitié de la liste et permuter l'élément à l'index 0
avec son miroir à l'index -1
dans la première itération. Ensuite, vous pouvez basculer l'élément à l'index 1
avec son miroir à l'index -2
et ainsi de suite jusqu'à ce que la liste soit inversée.
Voici une représentation de l'ensemble du processus :
Pour traduire ce processus en code, vous pouvez utiliser un pour
boucle avec un intervalle
objet sur la première moitié de la liste, que vous pouvez obtenir avec len(chiffres) // 2
. Ensuite, vous pouvez utiliser une instruction d'affectation parallèle pour échanger les éléments, comme ceci :
>>> chiffres = [[[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> pour je dans intervalle(longueur(chiffres) // 2):
... chiffres[[[[je], chiffres[[[[-1 - je] = chiffres[[[[-1 - je], chiffres[[[[je]
...
>>> chiffres
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Cette boucle parcourt un intervalle
objet qui va de 0
à len(chiffres) // 2
. Chaque itération échange un élément de la première moitié de la liste avec son équivalent miroir dans la seconde moitié. L'expression -1 - je
à l'intérieur de l'opérateur d'indexation, []
, garantit l'accès à l'élément miroir. Vous pouvez également utiliser l'expression -1 * (je + 1)
pour fournir l'index miroir correspondant.
Outre l'algorithme ci-dessus, qui tire parti de substitution d'index, il existe plusieurs façons d'inverser les listes à la main. Par exemple, vous pouvez utiliser .pop()
et .insérer()
comme ça:
>>> chiffres = [[[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> pour je dans intervalle(longueur(chiffres)):
... dernier_élément = chiffres.pop()
... chiffres.insérer(je, dernier_élément)
...
>>> chiffres
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Dans la boucle, vous appelez .pop()
sur la liste d'origine sans arguments. Cet appel supprime et renvoie le dernier élément de la liste, vous pouvez donc le stocker dans dernier_élément
. Puis .insérer()
se déplace dernier_élément
à la position à l'index je
.
Par exemple, la première itération supprime 9
à partir de l'extrémité droite de la liste et la stocke dans dernier_élément
. Ensuite, il insère 9
à l'index 0
. L'itération suivante prend 8
et le déplace vers l'index 1
, etc. À la fin de la boucle, vous obtenez la liste inversée en place.
Création de listes inversées
Si vous souhaitez créer une copie inversée d'une liste existante en Python, vous pouvez utiliser renversé()
. Avec une liste comme argument, renversé()
renvoie un itérateur qui produit des éléments dans l'ordre inverse :
>>> chiffres = [[[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> chiffres_inversés = renversé(chiffres)
>>> chiffres_inversés
>>> liste(chiffres_inversés)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Dans cet exemple, vous appelez renversé()
avec chiffres
comme argument. Ensuite, vous stockez l'itérateur résultant dans chiffres_inversés
. L'appel à liste()
consomme l'itérateur et renvoie une nouvelle liste contenant les mêmes éléments que chiffres
mais dans l'ordre inverse.
Un point important à noter lorsque vous utilisez renversé()
est qu'il ne crée pas de copie de la liste d'entrée, donc les modifications qui y sont apportées affectent l'itérateur résultant :
>>> des fruits = [[[["Pomme", "banane", "Orange"]
>>> fruit_renversé = renversé(des fruits) # Obtenez l'itérateur
>>> des fruits[[[[-1] = "kiwi" # Modifier le dernier élément
>>> suivant(fruit_renversé) # L'itérateur voit le changement
'kiwi'
Dans cet exemple, vous appelez renversé()
pour obtenir l'itérateur correspondant sur les éléments dans des fruits
. Ensuite, vous modifiez le dernier fruit. Ce changement affecte l'itérateur. Vous pouvez le confirmer en appelant suivant()
pour obtenir le premier élément dans fruit_renversé
.
Si vous avez besoin d'obtenir une copie de des fruits
utilisant renversé()
, alors vous pouvez appeler liste()
:
>>> des fruits = [[[["Pomme", "banane", "Orange"]
>>> liste(renversé(des fruits))
['orange', 'banana', 'apple']
Comme vous le savez déjà, l'appel à liste()
consomme l'itérateur qui résulte de l'appel renversé()
. De cette façon, vous créez une nouvelle liste en tant que copie inversée de l'originale.
Python 2.4 ajouté renversé()
, un outil universel pour faciliter itération inverse sur des séquences, comme indiqué dans le PEP 322. En général, renversé()
peut prendre tous les objets qui implémentent un .__renversé__()
méthode ou qui prennent en charge la protocole de séquence, composé du .__len__()
et .__obtenir l'article__()
méthodes spéciales. Donc, renversé()
ne se limite pas aux listes :
>>> liste(renversé(intervalle(dix)))
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> liste(renversé("Python"))
['n', 'o', 'h', 't', 'y', 'P']
Ici, au lieu d'une liste, vous passez un intervalle
objet et une chaîne comme arguments de renversé()
. La fonction fait son travail comme prévu et vous obtenez une version inversée des données d'entrée.
Un autre point important à souligner est que vous ne pouvez pas utiliser renversé()
avec des itérateurs arbitraires :
>>> chiffres = itérer([[[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> renversé(chiffres)
Traceback (appel le plus récent en dernier) :
Déposer "" , ligne 1, dans
Erreur-type: L'objet 'list_iterator' n'est pas réversible
Dans cet exemple, iter()
construit un itérateur sur votre liste de nombres. Quand vous appelez renversé()
au chiffres
, vous obtenez un Erreur-type
.
Les itérateurs implémentent le .__suivant__()
méthode spéciale pour parcourir les données sous-jacentes. On s'attend également à ce qu'ils mettent en œuvre le .__iter__()
méthode spéciale pour retourner l'instance d'itérateur actuelle. Cependant, ils ne sont pas censés mettre en œuvre non plus .__renversé__()
ou le protocole de séquence. Donc, renversé()
ne fonctionne pas pour eux. Si jamais vous avez besoin d'inverser un itérateur comme celui-ci, vous devez d'abord le convertir en une liste en utilisant liste()
.
Un autre point à noter est que vous ne pouvez pas utiliser renversé()
avec des itérables non ordonnés :
>>> chiffres = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
>>> renversé(chiffres)
Traceback (appel le plus récent en dernier) :
Déposer "" , ligne 1, dans
Erreur-type: l'objet 'set' n'est pas réversible
Dans cet exemple, lorsque vous essayez d'utiliser renversé()
avec un ensemble
objet, vous obtenez un Erreur-type
. C'est parce que les ensembles ne gardent pas leurs éléments ordonnés, donc Python ne sait pas comment les inverser.
Inverser les listes grâce au découpage
Depuis Python 1.4, la syntaxe de découpage a un troisième argument, appelé marcher
. Cependant, cette syntaxe ne fonctionnait initialement pas sur les types intégrés, tels que les listes, les tuples et les chaînes. Python 2.3 a étendu la syntaxe aux types intégrés, vous pouvez donc utiliser marcher
avec eux maintenant. Voici la syntaxe de découpage complète :
Cette syntaxe permet d'extraire tous les éléments de une liste
de démarrer
à arrêt − 1
par marcher
. Le troisième décalage, marcher
, la valeur par défaut est 1
, c'est pourquoi une opération de tranchage normale extrait les éléments de gauche à droite :
>>> chiffres = [[[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> chiffres[[[[1:5]
[1, 2, 3, 4]
Avec [1:5]
, vous obtenez les éléments de l'index 1
indexer 5 - 1
. L'élément avec l'indice égal à arrêter
est jamais inclus dans le résultat final. Ce découpage renvoie tous les éléments de la plage cible car marcher
par défaut à 1
.
Noter: Vous pouvez omettre le deuxième deux-points (:
) dans un opérateur de découpage lorsque la valeur par défaut (1
) répond à vos besoins actuels.
Si vous utilisez un autre marcher
, alors le tranchage saute autant d'éléments que la valeur de marcher
:
>>> chiffres = [[[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> chiffres[[[[0::2]
[0, 2, 4, 6, 8]
>>> chiffres[::[::[::[::3]
[0, 3, 6, 9]
Dans le premier exemple, [0::2]
extrait tous les éléments de l'index 0
jusqu'à la fin de chiffres
, en sautant par-dessus deux éléments à chaque fois. Dans le deuxième exemple, le tranchage saute 3
articles au fur et à mesure. Si vous ne fournissez pas de valeurs à démarrer
et arrêter
, puis ils sont réglés sur 0
et à la longueur de la séquence cible, respectivement.
Si vous définissez marcher
à -1
, alors vous obtenez une tranche avec les éléments dans l'ordre inverse :
>>> chiffres = [[[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> # Définir le pas à -1
>>> chiffres[[[[longueur(chiffres) - 1::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> chiffres
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Ce découpage renvoie tous les éléments de l'extrémité droite de la liste (len(chiffres) - 1
) vers l'extrémité gauche car vous omettez le deuxième décalage. Le reste de la magie dans cet exemple vient de l'utilisation d'une valeur de -1
pour marcher
. Lorsque vous exécutez cette astuce, vous obtenez une copie de la liste d'origine dans l'ordre inverse sans affecter les données d'entrée.
Si vous comptez entièrement sur les décalages implicites, la syntaxe de découpage devient plus courte, plus propre et moins sujette aux erreurs :
>>> chiffres = [[[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> # Se fier aux valeurs de décalage par défaut
>>> chiffres[::[::[::[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Ici, vous demandez à Python de vous donner la liste complète ([::-1]
) mais en passant en revue tous les éléments de l'arrière vers l'avant en définissant marcher
à -1
. C'est plutôt chouette, mais renversé()
est plus efficace en termes de temps d'exécution et d'utilisation de la mémoire. C'est aussi plus lisible et explicite. Ce sont donc des points à considérer dans votre code.
Une autre technique pour créer une copie inversée d'une liste existante consiste à utiliser tranche()
. La signature de cette fonction intégrée est comme ceci :
Cette fonction fonctionne de manière similaire à l'opérateur d'indexation. Il prend trois arguments avec une signification similaire à ceux utilisés dans l'opérateur de découpage et renvoie un objet slice représentant l'ensemble des indices renvoyés par plage (démarrage, arrêt, pas)
. Cela semble compliqué, alors voici quelques exemples de la façon dont tranche()
travaux:
>>> chiffres = [[[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> tranche(0, longueur(chiffres))
tranche (0, 10, aucun)
>>> chiffres[[[[tranche(0, longueur(chiffres))]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> tranche(longueur(chiffres) - 1, Rien, -1)
tranche(9, Aucun, -1)
>>> chiffres[[[[tranche(longueur(chiffres) - 1, Rien, -1)]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Le premier appel à tranche()
est équivalent à [0:len(digits)]
. Le deuxième appel fonctionne de la même manière que [len(digits) - 1::-1]
. Vous pouvez également émuler le tranchage [::-1]
utilisant tranche(Aucun, Aucun, -1)
. Dans ce cas, passer Rien
à démarrer
et arrêter
signifie que vous voulez une tranche du début à la fin de la séquence cible.
Noter: Sous le capot, des littéraux tranchés créent tranche
objets. Ainsi, lorsque vous omettez un décalage comme dans [::-1]
, ça marche comme si tu passais Rien
au décalage correspondant dans un appel à tranche()
.
Voici comment vous pouvez utiliser tranche()
pour créer une copie inversée d'une liste existante :
>>> chiffres = [[[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> chiffres[[[[tranche(Rien, Rien, -1)]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
le tranche
objet extrait tous les éléments de chiffres
, en partant de l'extrémité droite jusqu'à l'extrémité gauche, et renvoie une copie inversée de la liste cible.
[ad_2]