E

Both cycles are the same. Only entry lists are different. You remove the elements from the list while circling it.Bypassing the list, cycle for Not copying. It creates a terator that's the elements on the list. one He's coming back. So when you remove the element (.remove('0') Looking for one. '0' on the list and removes it), the list changes and these changes are visible in the terator. In the current implementation of the CPython, the list terator retains the reference to the list itself and the current index. Elements return as long as the list is longer than the current index. That's the point. https://github.com/python/cpython/blob/63718f4154b0cb0e0bc672b6c38e00dfef70d111/Objects/listobject.c#L2765-L2787 returning the following element to each iteration:listiter_next(listiterobject *it)
{
...
if (it->it_index < PyList_GET_SIZE(it->it_seq)) {
item = PyList_GET_ITEM(seq, it->it_index);
++it->it_index;
return item;
}
...
}
What does Pitton look like:if i < len(lst):
item = lst[i]
i += 1
return item
If you move on with the code http://pythontutor.com/visualize.html#code=lst%20%3D%20%5B0,%20 :#XXX BROKEN
lst = [0, '0', '0', '0', '0', '0', '0', '0', '0', 9]
for i, x in enumerate(lst):
lst.remove('0')
size = len(lst)
print(lst) # -> [0, '0', '0', '0', 9]
You can see that the cycle is going on until i < size♪ The cycle can therefore be completed before all '0' The elements are removed.If you want to delete '0' From the list, that's the usual way:lst[:] = [x for x in lst if x != '0']
If you don't set up a temporary list, you can, bypassing the list, move the meanings that you want to leave on the list, then https://stackoverflow.com/a/2794519/4279 :def remove_all(seq, value):
pos = 0
for item in seq:
if item != value:
seq[pos] = item
pos += 1
del seq[pos:]
remove_all(lst, '0')
Both linear decisionsO(n)♪ The first decision requires O(n-k) additional memory where k = lst.count('0')♪If it is known that on the big list, only a few values need to be removed (k small and independent nor may be disposed of del lst[i]bypassing the list in reverse (as removal does not affect the elements at the beginning of the list):for i in reversed(range(len(lst))):
if lst[i] == '0':
del lst[i] # O(n) * k == O(n * k)
Anyway, it's a square algorithm. O(n**2)♪ The bad square algorithms.Quarterly solutions can be seen to be slower for nmore linear.For example, the linear algorithm for a list with millions of elements requires no more than C1 * 1000_000 Steps (instructions), while square algorithm C2 * 1000_000_000_000where C1, C2 constants are not dependent on the size of the entry list. C1, C2 is approximately (by order) equal in this case, so linear algorithm is much preferable if k ~ n♪If a million instructions are executed in about a millisecond (even if you can't blink) the square algorithm will be taken all day if someone's patience is enough to wait or the battery is not going to end.A million elements are not a major input under modern conditions (the memorial hygigaphones have).Normally, constants can be ignored (C1♪ C2 Outside hot spots (hot spots), for example, if the stop to order changes 10 times, a million linear algorithm instructions will take 10 times longer: ~10 milliseconds (all faster than blink) and much less than many hours for square algorithm from ~1012 operations.By writing algorithms, it is necessary to focus on simplicity, readability, and whether it can, in principle, carry out the task. Micro-optimizations that breed the code, only improving the contus.C1♪ C2 If the profiler doesn't say otherwise. If it is not known in advance that the introduction is limited in size, attention should be paid to the growth (big O) of the algorithm used. In particular, linear algorithms (in particular, if this is not a significant barrier to implementation)O(n)() much preferable to square (O(n*n)) Examples from the real world: https://accidentallyquadratic.tumblr.com/