pythonlistsortingpython-internals

Accessing the list while being sorted


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 []?


Solution

  • 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