用于在 PEP 3113 之后对没有幻数的元组进行排序的 `key` 函数

Posted

技术标签:

【中文标题】用于在 PEP 3113 之后对没有幻数的元组进行排序的 `key` 函数【英文标题】:`key` function for sorting tuples without magic numbers after PEP 3113 【发布时间】:2015-05-17 16:26:26 【问题描述】:

为我的程序提供了一个数据源,其中包含“值”和“出现次数”列,作为元组 (value, frequency) 的集合。在 Python 2.6 或 2.7 中,我会这样做:

ls.sort(key=lambda (value, frequency): -frequency)

但是 Python 3 移除了解压元组参数的能力。在命名函数中并没有那么大的伤害,因为可以在函数体中使用赋值语句解包 (Nested arguments in python not compiling)。但是因为lambda body 不能使用赋值语句,所以不能以这种方式解包(Python lambda does not accept tuple argument)。

PEP 3113 推荐这种解决方法:

ls.sort(key=lambda row: -row[1])

但是这种使用1 作为magic number 在我的嘴里留下了不好的味道。在 Python 3 中使用这种神奇的数字是惯用的吗?或者我应该为之前在 lambda 中使用元组解包的每种情况创建一个命名函数,就像这样?

def negative_of_frequency_from_value_frequency_tuple(value_freq):
    value, freq = value_freq
    return -freq

ls.sort(key=negative_of_frequency_from_value_frequency_tuple)

或者我是否应该让提供这些元组的库的作者返回 named tuples 而不是普通元组?

【问题讨论】:

为了避免幻数,你可以做例如VALUE_INDEX, FREQ_INDEX = range(2). 使用幻数作为索引是可以的;如果您真的不想要一个可以任意位于中间的索引,请使用-row[-1],这将绝对指示最后一个索引。 对我(和代码检查程序)来说,未使用的本地名称是一种代码气味。我会使用你所谓的解决方法lambda r: -r[1],即使在 2.x 中也是如此。 【参考方案1】:

如果您只需要单层解构,则可以使用包装器获得相同的效果。

ls.sort(key=lambda x: (lambda value, frequency: frequency)(*x))

如果您需要多个级别,请使用推导式

ls.sort(key=lambda x: next(-frequency for value, frequency in [x]))

【讨论】:

以上是关于用于在 PEP 3113 之后对没有幻数的元组进行排序的 `key` 函数的主要内容,如果未能解决你的问题,请参考以下文章

对深度嵌套的元组进行排序

对具有名称的元组列表进行排序[重复]

PEP8-python编码规范(下)

如何同时使用两个功能对 RDD 条目进行排序?

如何对返回 orm 对象和自定义列的元组的查询进行正确排序、分组?

对有符号整数内的元组进行排序