Can I access a list while it is being sorted in the list.sort()
b = ['b', 'e', 'f', 'd', 'c', 'g', 'a']
f = 'check this'
def m(i):
print i, b, f
return None
b.sort(key=m)
print b
this returns
b [] check this
e [] check this
f [] check this
d [] check this
c [] check this
g [] check this
a [] check this
Note that individual items of list b
is sent to function m
. But at m
the list b
is empty, however it can see the variable f
, which has same scope as list b
. Why does function m
print b
as []
?
Looking at the source code (of CPython, maybe different behaviour for other implementations) the strange output of your script becomes obvious:
/* The list is temporarily made empty, so that mutations performed
* by comparison functions can't affect the slice of memory we're
* sorting (allowing mutations during sorting is a core-dump
* factory, since ob_item may change).
*/
saved_ob_size = Py_SIZE(self);
saved_ob_item = self->ob_item;
saved_allocated = self->allocated;
Py_SET_SIZE(self, 0);
The comment says it all: When you begin sorting, the list is emptied. Well, it is "empty" in the eye of an external observer.
I quite like the term "core-dump factory".
Compare also:
b = ['b','e','f','d','c','g','a']
f = 'check this'
def m(i):
print i, b, f
return None
b = sorted(b, key= m)
print b
This is something you can't rely on in general - not just for lists - unless the documentation for the method you're using explicitly says otherwise. Accessing an object in an intermediate state - ie, after some iteration has been started, but before it has been finished - is a problem that concurrent code runs into a lot. You've found a rare non-concurrent case of it, but the advice is the same: avoid this situation. The intermediate state is not guaranteed to be meaningful to you, and is not guaranteed to be a "valid" state according to the rules of that object (when it tends to be called an "inconsistent" state).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With