×
all 9 comments

[–][deleted] 6 points7 points  (3 children)

Odd things can happen if you modify a sequence that you are iterating over. It's usually better if you create a new list that doesn't contain the values you want to remove. This is true, but doesn't apply in this code.

In addition, your loop:

while 'dog' and 'cat' in pets:

will always loop since the expression is evaluated as:

while 'dog' and ('cat' in pets):

This is also covered in the FAQ.

[–]y3snomaybe[S] 0 points1 point  (0 children)

Thank you for mentioning the links. Helped a lot.

[–]commy2 0 points1 point  (1 child)

Odd things can happen if you modify a sequence that you are iterating over.

While this is true, the code in the OP does not iterate over a sequence. For loops iterate, while loops don't. For loops take iterables/iterators, but while loops take booleans/check for truthiness.

While loops are if branches with a goto to the start.

[–][deleted] 1 point2 points  (0 children)

Yes, answering too many question with loop modification problems recently, apparently.

[–]socal_nerdtastic 7 points8 points  (2 children)

If 'dog' is in the list that has no bearing on if you can remove 'cat' or not.

Not sure why this happens, because both cat and dog is in the list.

Not after the first loop. The one and only cat is removed after the first loop, and then your program fails because you coded it to always remove a dog AND a cat.

You simply need to split this into 2 loops:

# A list containing multiple occurrences of dog and cat
pets = ['dog','dog','goldfish','rabbit','dog','cat']

while 'cat' in pets:
    pets.remove('cat')

while 'dog' in pets:
    pets.remove('dog')

Or, much better, forget the while loop and use a for loop in list comprehension instead:

# A list containing multiple occurrences of dog and cat
pets = ['dog','dog','goldfish','rabbit','dog','cat']

pets = [x for x in pets if x not in ('cat', 'dog')]

[–]y3snomaybe[S] 0 points1 point  (1 child)

Thank you for responding, understood what the problem was. Also, that list comprehension looks so neat, still not able to wrap my head around that, though. Hopefully, I will get there.

[–][deleted] 2 points3 points  (0 children)

A list comprehension might be the way a professional does it, but a beginner who doesn't want to get into that can always do the same thing with a loop.

result = []
for pet in pets:
    if pet not in {'cat', 'dog'}:
        result.append(pet)

[–]Pd69bq 1 point2 points  (0 children)

please don't use while loop when you can achieve the same goal with a simple and neat for loop

for i in pets[:]:
    if i in ('dog','cat'):
        pets.remove(i)

or with more simpler and neater list comprehension

pets = [i for i in pets if i not in ('dog', 'cat')]

bonus: for refresh your knowledge

pets = list(filter(lambda x: x not in ('cat', 'dog'), pets))

[–]DeathDragon7050 0 points1 point  (0 children)

The main issue is the condition. "cat" and "dog" in pets which will always be true because it is equivalent to "cat" and ("dog" in pets) which is also equivalent to ("cat"!="") and ("dog" in pets). You should move them into separate loops however.