[Tutor] list method help

Chris or Leslie Smith smiles at worksmail.net
Fri Feb 3 08:15:03 CET 2006


| Hello,
|          was just trying to do something and tried the following code:
| 
| list = ["1", "test", "1.5"]
| 
| for x in list:
|     print list.pop(x)
| 
| I get the following error:
| 
| print list.pop(x)
| TypeError: an integer is required
| 
| Does this mean i can't use a for loop to pop things from a list? or is
| there another way to do it?

In the interactive window you can request help to see if that gives you a clue as to what might be going wrong:

###
>>> help(list.pop)
Help on method_descriptor:

pop(...)
    L.pop([index]) -> item -- remove and return item at index (default last)

###

So you must supply an index (which is an integer) defining which item you want to remove (or else supply no argument and automatically get the default which is the last item). You should not tell pop *what* you want to pop--which is what you did with the "x"--you should tell it which item *number* you want to pop--which you did in your next attempt.

| 
| I also tried the following:
| 
| list = ["1", "test", "1.5"]
| 
| for x in list:
|     print list.pop(0)
| 
| which worked but returned the following:
| 
| 1
| test
| 
| Why did it not return the last value in the list?
| 

The "for x in list" is shorthand for the following equivalent syntax:

i=0
while i <len(list):
    ...
    #your code
    ...
    i=i+1

So here's what's happening:

first pass, i=0, list length is 3; enter loop and pop off the '1'
second pass, i=1, list length is 2; enter loop and pop off the 'test'
third pass, i=2, list length is 1; the loop is not entered

The "i" here is something that the "for x in l" is keeping track of. Since it is 2 on your attempted 3rd pass and this is greater than the length of the list at that point, you never get inside the loop and you don't see the last item popped off. (See below for a little tangent on the "i" and "l" that are being used.)

If you really want to pop off all 3 elements, then you could reference a list that doesn't change as you pop off the elements that has the same length as your list:

for x in range(len(list)):
    print list.pop(0)

NOTE: a list is created by range *once* and is not created each time the loop is run, so for your list, range(len(list)) => range(3) => [0, 1, 2]

Another approach you could use is to keep popping off elements until the list is consummed:

while list:
    print list.pop(0)

-----------------
OK, here's the aside--you might want to skip this for now.
-----------------

If we reshuffle the list while we are walking through it, we can keep printing the same thing (not that we would really want to, but you get the idea that some internal index is advancing you through the list)
###
>>> for x in l:
...  print x,l
...  l[:]=l[-1:]+l[0:-1] #rotate the list to the right
...  
1 ['1', 'test', '1.5']
1 ['1.5', '1', 'test']
1 ['test', '1.5', '1']
###

But here is the first attempt that I made to do this and it gave a different result:
###
>>> for x in l:
...  print x,l
...  l=l[-1:]+l[0:-1]
...  
1 ['1', 'test', '1.5']
test ['1.5', '1', 'test']
1.5 ['test', '1.5', '1']
###

So it appears that not only does the "for x in l" keep track of an index, it also keeps track of the original 'l' and allows me to point an 'l' in the loop to something separate from the one it is keeping track of. So it seems the "for x in l" is doing something like:

i=0
tempList = list
while i<len(tempList):
    ...
    i=i+1

In the attempt at redefining 'l' that I showed first above, I was not making 'l' point at something new, I was modifying elements of the thing that 'l' pointed to which was also the thing that 'tempList' was pointing to so I always saw the '1' printed since the list rotation caused this alway to be the next thing. In the second example, I was creating something different from tempList and so I wasn't seeing those elements being printed. This concept of 'pointing' can be shown with the following:

###
>>> l=range(3)
>>> a=l     # 'a' is pointing at what 'l' is pointing at
>>> l[0]=42 # I make a change to the thing that 'l' points to
>>> print a
[42, 1, 2]
>>> print l
[42, 1, 2]
>>> 
###

Since a and l point at the same thing, they both show the change. But compare that to this:

###
>>> l=range(3)
>>> a=l  # 'a' and 'l' point to the same thing
>>> l=42 # here I make 'l' point to something else
>>> print a
[0, 1, 2]
>>> print l
42
###

This perplexing issue is something that bites most of us at some time. I hope I haven't made it more perplexing ;-) If you have more questions, ask. 

/c


More information about the Tutor mailing list