| 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
_______________________________________________
Tutor maillist - [email protected]
http://mail.python.org/mailman/listinfo/tutor