The first test isn't surprising; three elements are removed off the end.
The second test is a bit surprising. Only two elements are removed. Why?
List iteration in Python essentially consists of an incrementing index into the list. When you delete an element you shift all the elements on the right over. This may cause the index to point to a different element.
Illustratively:
start of loop
[0,0,0,1,2,3,4,5,6]
^ <-- position of index
delete first element (since current element = 0)
[0,0,1,2,3,4,5,6]
^
next iteration
[0,0,1,2,3,4,5,6]
^
delete first element (since current element = 0)
[0,1,2,3,4,5,6]
^
and from now on no zeros are encountered, so no more elements are deleted.
To avoid confusion in the future, try not to modify lists while you're iterating over them. While Python won't complain (unlike dictionaries, which cannot be modified during iteration), it will result in weird and usually counterintuitive situations like this one.
Answer from nneonneo on Stack OverflowThe first test isn't surprising; three elements are removed off the end.
The second test is a bit surprising. Only two elements are removed. Why?
List iteration in Python essentially consists of an incrementing index into the list. When you delete an element you shift all the elements on the right over. This may cause the index to point to a different element.
Illustratively:
start of loop
[0,0,0,1,2,3,4,5,6]
^ <-- position of index
delete first element (since current element = 0)
[0,0,1,2,3,4,5,6]
^
next iteration
[0,0,1,2,3,4,5,6]
^
delete first element (since current element = 0)
[0,1,2,3,4,5,6]
^
and from now on no zeros are encountered, so no more elements are deleted.
To avoid confusion in the future, try not to modify lists while you're iterating over them. While Python won't complain (unlike dictionaries, which cannot be modified during iteration), it will result in weird and usually counterintuitive situations like this one.
since in list or Stack works in last in first out[LIFO] so pop() is used it removes last element in your list
where as pop(0) means it removes the element in the index that is first element of the list
as per the Docs
list.pop([i]):
Remove the item at the given position in the list, and return it. If no index is specified, a.pop() removes and returns the last item in the list. (The square brackets around the i in the method signature denote that the parameter is optional, not that you should type square brackets at that position. You will see this notation frequently in the Python Library Reference.)
Why do we use pop(0) instead of pop()?
I don't think I understand what the .pop() method does on a list....
[Beginner] What's the difference between list = list[1:] and list.pop(0)? Should lead to the same result, right?
python - How does CPython implement pop(0)? - Stack Overflow
Videos
L=[1,2,3,4,5,6]
for element in L: print(L,element) L.pop(0)
I have the code above. This code returns the following:
[1, 2, 3, 4, 5, 6] 1 [2, 3, 4, 5, 6] 3 [3, 4, 5, 6] 5
I don't understand why the loop variable prints(1,3,5) here...
I don't know anything about C but want to share my insight and it'd be too long for a comment.
That's the pop implementation.
If pop arg is the last element in the list, it calls list_resize which doesn't seem to be too complicated.
if (index == Py_SIZE(self) - 1) {
status = list_resize(self, Py_SIZE(self) - 1);
if (status >= 0)
return v; /* and v now owns the reference the list had */
else
return NULL;
Otherwise list_ass_slice is called. It happens it has a comment in it
/* Because [X]DECREF can recursively invoke list operations on this list, we must postpone all [X]DECREF activity until after the list is back in its canonical shape. Therefore we must allocate an additional array, 'recycle', into which we temporarily copy the items that are deleted from the list. :-( */
I'd assume that's where the performance is lost, on this temporary allocation.
You're asking two separate questions.
Why is the list ID the same before and after popping? As @Naman Chikara has explained in the comments, this is because the ID of a mutable object doesn't change even if the object does.
Why is
pop()much faster thanpop(0)? The answer is here:
Here's my guess: pop() removes rightmost list element by shortening the length of the list by 1. pop(0) removes leftmost element by shifting the rest of the elements one place left and then shortening the length of the list by 1. It is the shifting that is taking a lot of time.
As in many languages, it's much easier to add/remove items from the right side of an array than from the left.
I'm assuming, based on your phrasing, that self.items is a list. The pop method for lists, as you've pointed out, can be used to remove and return an element of the list at a specified index. If you omit the index, then the last item is removed and returned.
Either way, pop returns the item that was removed. If you put [0] after the call to pop, you'll get the first item of the item that was popped. So, if self.items is [[1, 2, 3], [4, 5, 6]], then self.items.pop() would be [4, 5, 6] and therefore self.items.pop()[0] would be 4.
You can try it.
def pop(self):
if len(self.items) > 0:
return self.items[1].pop(0)
Her items[1] is items[items list index]
items = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]