用于在 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` 函数的主要内容,如果未能解决你的问题,请参考以下文章