huk*_*uan 22 python sorting list
我想按列表中元素的出现次数对列表进行排序.
当我使用这个表格时:
A=[2,1,3,4,2,2,3]
A.sort(key=lambda x:A.count(x))
print(A)
Run Code Online (Sandbox Code Playgroud)
结果不是我想要的:[2, 1, 3, 4, 2, 2, 3].
但是,当我使用sorted以下方式编写时:
B=sorted(A,key=lambda x:A.count(x))
print(B)
Run Code Online (Sandbox Code Playgroud)
结果是对的:[1, 4, 3, 3, 2, 2, 2].
这种行为的原因是什么?
ale*_*cxe 17
这是设计和有意的.CPython暂时"禁止"访问列表,同时对列表进行排序,此行为记录在此处:
CPython实现细节: 在对列表进行排序时,尝试变异甚至检查列表的效果是未定义的.Python的C实现使得列表在持续时间内显示为空,并且如果它可以检测到列表在排序期间已经变异,则会引发ValueError.
您可以通过A在键功能内打印来检查- 您将获得一个空列表:
In [2]: def key_function(x):
...: print(A, x)
...: return A.count(x)
...:
In [3]: A.sort(key=key_function)
([], 2)
([], 1)
([], 3)
([], 4)
([], 2)
([], 2)
([], 3)
Run Code Online (Sandbox Code Playgroud)
但是,如果你这样做sorted():
In [4]: sorted(A, key=key_function)
([2, 1, 3, 4, 2, 2, 3], 2)
([2, 1, 3, 4, 2, 2, 3], 1)
([2, 1, 3, 4, 2, 2, 3], 3)
([2, 1, 3, 4, 2, 2, 3], 4)
([2, 1, 3, 4, 2, 2, 3], 2)
([2, 1, 3, 4, 2, 2, 3], 2)
([2, 1, 3, 4, 2, 2, 3], 3)
Out[4]: [1, 4, 3, 3, 2, 2, 2]
Run Code Online (Sandbox Code Playgroud)
它也在sort()实现中记录:
/* 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).
*/.
Run Code Online (Sandbox Code Playgroud)
它似乎A在就地排序过程中发生了变化,因此您无法依赖A排序过程中的值.
制作副本也有效.
A=[2,1,3,4,2,2,3]
B=A[:]
A.sort(key=lambda x:B.count(x))
print(A)
Run Code Online (Sandbox Code Playgroud)
在python文档中通过这一行确认
CPython实现细节:在对列表进行排序时,尝试变异甚至检查列表的效果是未定义的.Python的C实现使得列表在持续时间内显示为空,并且如果它可以检测到列表在排序期间已经变异,则会引发ValueError.