newbie - infinite loop

Remco Gerlich scarblac at pino.selwerd.nl
Mon Mar 19 10:15:15 EST 2001


Paul Brian <pbrian at demon.net> wrote in comp.lang.python:
> I have solved the opriginal problem but am left with a serious question.
> 
> Before I discovered the keywords in and not in, I tried to count unique
> instances of names in a file.
> I devcided to create a (neaarly) empty list, compare each name in the file
> with that list. If the name was not in, append to list, otherwise leave it
> alone.

Your code belows does the opposite: if it *is* already in the list, append
it once more. And since you change the list you're currently looping over
(which is a mortal sin, etc) you get an infinite loop.

> After the following was run (and crashed) a couple of times I started using
> my brain and realised there must be some "in" operator. However the problem
> still stands - a for condition seems completely mutable.

It's a list. It's mutable. It's not a "for condition", for just tries to get
new elements from the list until that gives an error, then the loop is
finished. If you append to the list during the loop, the new elements are
also visited. If you add or delete things in the middle of the list,
anything might happen.

Do not taunt happy fun for loops. Do not change lists you are looping over.

> Surely this should not happen.  Surely the line 3 condition "for every
> element in this list", should not constantly expand but should be set solid
> till the next pass?
> 
> What have I done wrong - is it the mutable list v the immutable tuple
> problem (but it should work..surely?) Or is this just the way things are -
> "live with it and do not try anything like this again?"
> 
> thanks in advance
> ==============
> uniqueList = ['q']               # create an nearl empyty list (seems to
> ignore line 3 if truly empty)
> line = 'q'                          # fake the retrieval of line from file
> 
> for listElement in uniqueList:             #3
>     if listElement == line:                    #4
>         uniqueList.append(line)            #5 at this point it seems to
> think that there is now another list
>                                                         #element to compare
> and so loops for ever...help!
> 
> print len(uniqueList)

This idea would work something like this (although the better method is to
use a dictionary, see below):

uniqueList = []   # No words seen yet
line = 'q'        # Or get some line some other way

for listElement in uniqueList:
   if line == listElement:
      break   # Do nothing, we have this word already, stop the for loop
else:
   # The else clause runs after the for loop finishes, if no break was hit
   uniqueList.append(line)
   

But this still has to go through the whole list for every new word, which is
very slow. Use a dictionary, set dict["word"] to 1 for every word, it
doesn't matter if the word was already seen once since it's just
overwritten, at the end you have all the unique words in dict.keys():

uniqueDict = {}

# Do the following for every line, of course
line = 'q'
uniqueDict[line] = 1

# This prints all the unique lines we've seen
print uniqueDict.keys()

-- 
Remco Gerlich



More information about the Python-list mailing list