3
votes

Python for-in-loop arrête l'itération sur l'objet de liste créé à partir de for-in-loop

[Première question du tout premier utilisateur débutant de Stack-o-flow Python]

J'ai essayé de créer une fonction qui ajoute les nombres de 1 à 10 puis efface de 10 à 1 dans l'objet de liste python. J'ai réussi cependant, je suis tombé sur un comportement étrange de boucles for-in.

Voici ce que j'ai fait et réussi:

[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Length before passed:  10
Length BEFORE REMOVE:  10
Length AFTER REMOVE:  9
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Length BEFORE REMOVE:  9
Length AFTER REMOVE:  8
[1, 2, 3, 4, 5, 6, 7, 8]
Length BEFORE REMOVE:  8
Length AFTER REMOVE:  7
[1, 2, 3, 4, 5, 6, 7]
Length BEFORE REMOVE:  7
Length AFTER REMOVE:  6
[1, 2, 3, 4, 5, 6]
Length BEFORE REMOVE:  6
Length AFTER REMOVE:  5
[1, 2, 3, 4, 5] <---- And it stops here.

imprimerait:

def a():
    li = []
    for i in range(1,11):
        li.append(i)
        print(li)

    print("Length before passed: ", len(li))

    for n in li: <------------ THIS
        print("Length BEFORE REMOVE: ", len(li))

        li.remove(li[-1])

        print("Length AFTER REMOVE: ", len(li))
        print(li)
a()

Cependant, si je change la deuxième partie de sa boucle for range (1,11) en li , l'itération s'arrête comme indiqué ci-dessous.

[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5]

Serait imprimer:

def a():
    li = []

    for i in range(1,11):
        li.append(i)
        print(li)

    for n in li:         <-------------- THIS PART
        li.remove(li[-1])
        print(li)

a()

Donc, j'ai vérifié sa longueur de l'objet li .

[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5]
[1, 2, 3, 4]
[1, 2, 3]
[1, 2]
[1]
[]

Serait imprimer:

def a():
    li = []

    for i in range(1,11):
        li.append(i)
        print(li)

    for n in range(1,11):
        li.remove(li[-1])
        print(li)

a()

Que se passe-t-il ici? Pourquoi python for-loop s'arrêterait-il avant son cycle complet?

Merci beaucoup.


4 commentaires

Qu'est-ce que st ? Je ne vois pas de définition


Mon mauvais, tout premier utilisateur de stack-o-flow. Mis à jour.


Règle n ° 1: ne supprimez pas les éléments de la liste lors de son itération.


Merci Austin !!


4 Réponses :


4
votes

Essayez d'exécuter ceci, vous comprendrez immédiatement

[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
1
[1, 2, 3, 4, 5, 6, 7, 8, 9]
2
[1, 2, 3, 4, 5, 6, 7, 8]
3
[1, 2, 3, 4, 5, 6, 7]
4
[1, 2, 3, 4, 5, 6]
5
[1, 2, 3, 4, 5]

En supprimant des éléments, cela se produit:

def a():
    li = []

    for i in range(1,11):
        li.append(i)
        print(li)

    for n in li:
        print(n)
        li.remove(li[-1])
        print(li)

a()


0 commentaires

5
votes

Dans votre cas, l'itération s'arrête car vous effectuez une itération depuis le début, mais vous supprimez des éléments de la fin en même temps:

  • La 1ère itération se termine par 9 éléments, donc la boucle passe au 2ème élément.
  • La 2ème itération se termine par 8 éléments, donc la boucle passe au 3ème élément
  • ...
  • La 5ème itération se termine par 5 éléments, il n'y a pas de 6ème élément vers lequel passer et la boucle se termine.

C'est pourquoi il est généralement déconseillé de faire muter une liste lors de son itération.


1 commentaires

SENSATIONNEL. Tu es incroyable.



0
votes

Vous ajoutez puis imprimez 10 fois, vous supprimez puis imprimez 10 fois - simplifié:

    for _ in  range(len(li)-1): # one less so it stops bevore removing the last elem
        li.pop()
        print(li)

Vous commencez avec une liste vide et imprimer après l'ajout - vous vous arrêtez avec une liste vide et imprimez.

Le problème avec la deuxième partie de code est: vous modifiez un itérable pendant l'itération - c'est généralement une mauvaise idée.

Si vous modifiez:

def a():
    li = []

    for i in range(1,11):
        li.append(i)
        print(li)

    while(li):
        li.pop()  # same but easier - removes last element without params
        if(li):   # test if non empty
            print(li)

ou optimisé:

a = []
a.append(1)
print(a)         # [1]
a.pop()
print(a)         # []

vous obtenez le résultat souhaité. p>


2 commentaires

Merci pour votre aimable réponse !!! Mais je suis toujours en boucle avec le chapitre de la liste. J'y arriverai dès que possible !!


Mais cette range (len (li) -1) est très utile !! Merci encore!!



0
votes

C'est parce que vous itérez la liste du début à la fin et que vous supprimez toujours le dernier élément. Comme la méthode remove modifie la liste et que la boucle for-in de python considère ces modifications, vous parcourez les cinq premiers itens et supprimez les cinq derniers.

Ma suggestion est de faire quelque chose comme ceci:

def a():
  li = []

  for i in range(1,11):
    li.append(i)
    print(li)

  print("Length before passed: ", len(li))

  # Remove the last item while has items
  while len(li):
    li.pop()


0 commentaires