为什么cmp()函数很有用?

23
根据文档和此教程cmp()函数有以下返回值:

如果 x < y,则返回 -1

如果 x == y,则返回 0

如果 x > y,则返回 1

该教程还提到:

cmp()函数返回两个数字之差的符号

我不太明白什么是“两个数字之差的符号”。那难道不意味着在数字的符号不相等时返回一个值吗?因为...

cmp(80, 100) :  -1      # both have positive sign.
cmp(180, 100) :  1      # both also have positive sign.
cmp(-80, 100) :  -1
cmp(80, -100) :  1

**注意:来自教程的代码。*

尽管我对符号差异感到困惑,但我实在想不出为什么我们需要一个内置函数在x < y时返回-1的值。

cmp( )函数不是很容易实现吗?Python创建者保留cmp()函数是否有任何原因,或者Python cmp() 函数有任何隐藏的用途?

5个回答

29

为什么cmp( )有用?

它并不是非常有用,这就是为什么它被弃用了(Python 3中已经删除了内置的cmp,内置排序也不再接受)。富比较方法取代了它:

object.__lt__(self, other)
object.__le__(self, other)
object.__eq__(self, other)
object.__ne__(self, other)
object.__gt__(self, other)
object.__ge__(self, other)

这使得<符号(以及其他符号)可以被重载比较运算符,从而使集合对象的子集和超集比较成为可能。

>>> set('abc') < set('cba')
False
>>> set('abc') <= set('cba')
True
>>> set('abc') == set('cba')
True
>>> set('abc') >= set('cba')
True
>>> set('abc') > set('cba')
False

虽然它可以实现上述功能,但cmp不允许以下操作:

>>> set('abc') == set('bcd')
False
>>> set('abc') >= set('bcd')
False
>>> set('abc') <= set('bcd')
False

cmp的玩具用法

这里有一个有趣的用法,它使用cmp的结果作为索引(如果第一个小于第二个,则返回-1;如果相等,则返回0;如果大于,则返回1):

def cmp_to_symbol(val, other_val):
    '''returns the symbol representing the relationship between two values'''
    return '=><'[cmp(val, other_val)]

>>> cmp_to_symbol(0, 1)
'<'
>>> cmp_to_symbol(1, 1)
'='
>>> cmp_to_symbol(1, 0)
'>'
根据文档,你应该把`cmp`当作不存在来处理:
请参考:https://docs.python.org/3/whatsnew/3.0.html#ordering-comparisons

cmp已移除,等效操作

但你可以使用以下代码进行替代:
(a > b) - (a < b)

在我们的小玩具函数中,即这个:

def cmp_to_symbol(val, other_val):
    '''returns the symbol representing the relationship between two values'''
    return '=><'[(val > other_val) - (val < other_val)]

来自PEP 207:“主要动机来自NumPy,其用户认为A<B应返回一个元素比较结果的数组;他们目前必须将其拼写为less(A,B),因为A<B只能返回布尔结果或引发异常。” - Levi Morrison
你关于集合和>=的那一段并不完全正确,因为cmp可以针对这些情况返回适当的结果。但是对于我之前评论中提到的NumPy情况则不适用。 - Levi Morrison
@LeviMorrison PEP 207是一个非常好的观点,我稍后会提到。现在 - 对于两个具有每个差异和交集的集合,什么是适当的结果(例如set('ab')set('bc'))?这些集合没有顺序,目前测试等式为False,小于和大于,并且cmp因此没有合理的结果,根据我的当前想法。 - Russia Must Remove Putin
啊,我忘记了在发布时>=是作为一个集合操作符。说实话,我认为这样做不是一个好主意——我不认为这种符号在集合论中被使用过,也不直观,至少对我来说不是——但是numpy在元素比较方面的用法似乎还不错。也许可以切换到一个numpy的例子? - Levi Morrison
@LeviMorrison 如果你提到了numpy,我可能会添加一个示例。我喜欢精心策划我的回答,所以如果你看到其他人有任何你想让我添加或批评的地方,请留下改进建议。 - Russia Must Remove Putin

11
我不太明白什么是“两个数字的差的符号”。这意味着:先计算它们的差,然后取该差的符号。例如,如果x和y是两个数字:
- x < y => x - y < 0,函数返回-1。 - x == y => x - y == 0,函数返回0。 - x > y => x - y > 0,函数返回1。
有关三路比较的更多信息,请参见Wikipedia

3
strcmp) 和 Perl (cmp) 都具有类似的操作(在这些情况下用于字符串,但是本质相同)。

2

1
另一个用例:查找数字的符号(- / +)
如果您想找出数字的符号(+/-),可以将0作为第二个参数轻松地传递给cmp函数。
cmp(-123, 0) #returns -1
cmp( 123, 0) #returns  1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接