在排序时访问列表

问题描述 投票:15回答:2

我可以在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

这回来了

b [] check this
e [] check this
f [] check this
d [] check this
c [] check this
g [] check this
a [] check this

请注意,列表b的各个项目将发送到函数m。但是在m,列表b是空的,但它可以看到变量f,其范围与列表b相同。为什么函数m打印b作为[]

python list sorting python-internals
2个回答
13
投票

查看source code(CPython,可能是其他实现的不同行为),脚本的奇怪输出变得明显:

/* 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_SIZE(self) = 0;

评论说明了一切:当您开始排序时,列表将被清空。嗯,它在外部观察者的眼中是“空的”。

我非常喜欢“核心转储工厂”这个词。


比较还:

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

4
投票

这是你不能依赖的东西 - 不仅仅是列表 - 除非你明确使用的方法的文档另有说明。访问处于中间状态的对象 - 即,在一些迭代开始之后,但在它完成之前 - 是并发代码运行很多的问题。你发现了一个罕见的非并发案例,但建议是一样的:避免这种情况。中间状态不保证对您有意义,并且根据该对象的规则(当它倾向于称为“不一致”状态时)不保证是“有效”状态。

© www.soinside.com 2019 - 2024. All rights reserved.