使用lambda时索引超出范围

San*_*tiy 12 python lambda

我现在对Python中的lambda运算符有点困惑.以下(工作)代码在所有元组的第一个元素上出现元组第一个元素的次数之后对元组列表进行排序:

tuples = [(2, 1, 8, 4), (3, 4, 8, 1), (3, 8, 1, 4), (4, 1, 8, 3),
              (4, 8, 1, 3), (8, 8, 3, 1), (8, 1, 3, 4), (8, 4, 1, 3),
              (8, 4, 3, 1)]

temp = list(zip(*tuples))    
tuples.sort(key=lambda x: temp[0].count(x[0])
                ,reverse=True)

print(tuples)
Run Code Online (Sandbox Code Playgroud)

但是,如果我现在尝试跳过创建"temp",即写下:

tuples = [(2, 1, 8, 4), (3, 4, 8, 1), (3, 8, 1, 4), (4, 1, 8, 3),
              (4, 8, 1, 3), (8, 8, 3, 1), (8, 1, 3, 4), (8, 4, 1, 3),
              (8, 4, 3, 1)]

tuples.sort(key=lambda x: list(zip(*tuples))[0].count(x[0])
                ,reverse=True)

print(tuples)
Run Code Online (Sandbox Code Playgroud)

它抛出一个错误:

Traceback (most recent call last):
  File "E:\Python-Programms\Sorting", line 6, in <module>
    ,reverse=True)
  File "E:\Python-Programms\Sorting", line 5, in <lambda>
    tuples.sort(key=lambda x: list(zip(*tuples)) [0].count(x[0])
IndexError: list index out of range
Run Code Online (Sandbox Code Playgroud)

为什么会出现此错误?

Mos*_*oye 12

如果您使用vanilla函数并在排序时打印列表,您会注意到在排序操作期间清除了列表(AFAIK适用于CPython).空列表没有索引零:

def f(x):
  print (tuples)
  return ...

tuples.sort(key=f ,reverse=True)

[]
[]
[]
[]
[]
[]
[]
[]
[]
Run Code Online (Sandbox Code Playgroud)

查看CPython源代码会给我们留下一个解释此行为的有用注释:

static PyObject *
list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse)
{
    ...
    /* 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)

对于你原来的问题,list.count你可以构建一个计数器然后用它来进行排序,而不是反复调用,这是非常低效的:

from collections import Counter

c = Counter([x[0] for x in tuples])
tuples.sort(key=lambda x: c[x[0]], reverse=True)
Run Code Online (Sandbox Code Playgroud)

  • 它被清除的事实被认为是一个实现细节; 在排序期间尝试检查列表被认为是未定义的行为,并且不同的Python实现可能表现不同. (5认同)