Python的:为什么int类不具有比较丰富的运营商,比如`__lt __()`?(Python:

2019-07-29 14:57发布

晴好奇。

我已经注意到了(至少在PY 2.6和2.7),一个float有大家所熟悉的丰富的比较函数: __lt__() __gt____eq__等。

>>> (5.0).__gt__(4.5)
True

但一个int

>>> (5).__gt__(4)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'int' object has no attribute '__gt__'

这是奇怪的我,因为运营商本身工作正常

>>> 5 > 4
True

即使字符串支持比较函数

>>> "hat".__gt__("ace")
True

但所有的int有被__cmp__()

觉得奇怪,我,所以我在想,为什么这个走过来的。

刚刚测试,它工作在Python 3如预期,所以我假定一些遗留的原因。 还是想听到一个适当的解释,虽然;)

Answer 1:

如果我们看一下PEP 207的富Comparisions有在年底这个有趣的句子权:

与整数比较交易已经存在的内联仍然适用,从而为最常见的情况没有任何性能开销。

如此看来,在2.x中存在整数比较优化。 如果我们的源代码来看看我们可以发现这一点:

case COMPARE_OP:
    w = POP();
    v = TOP();
    if (PyInt_CheckExact(w) && PyInt_CheckExact(v)) {
        /* INLINE: cmp(int, int) */
        register long a, b;
        register int res;
        a = PyInt_AS_LONG(v);
        b = PyInt_AS_LONG(w);
        switch (oparg) {
        case PyCmp_LT: res = a <  b; break;
        case PyCmp_LE: res = a <= b; break;
        case PyCmp_EQ: res = a == b; break;
        case PyCmp_NE: res = a != b; break;
        case PyCmp_GT: res = a >  b; break;
        case PyCmp_GE: res = a >= b; break;
        case PyCmp_IS: res = v == w; break;
        case PyCmp_IS_NOT: res = v != w; break;
        default: goto slow_compare;
        }
        x = res ? Py_True : Py_False;
        Py_INCREF(x);
    }
    else {
      slow_compare:
        x = cmp_outcome(oparg, v, w);
    }

如此看来,在2.x中有一个现有的性能优化 - 通过允许C代码直接比较整数 - 假若丰富的运营商相比已经执行了没有被保存下来。

现在,在Python 3 __cmp__不再支持如此丰富的比较运营商必须在那里。 现在,这并不引起,据我可以告诉创下性能。 例如,比较:

Python 2.7.1 (r271:86832, Jun 16 2011, 16:59:05) 
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import timeit
>>> timeit.timeit("2 < 1")
0.06980299949645996

至:

Python 3.2.3 (v3.2.3:3d0686d90f55, Apr 10 2012, 11:25:50) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import timeit
>>> timeit.timeit("2 < 1")
0.06682920455932617

如此看来,类似的优化是有,但我的猜测是主观判断是把他们都在2.x的分支将是太大的变化时,向后兼容性是一个考虑因素。

在2.x中,如果你想要的东西,如丰富的比较方法,你可以在他们通过让operator模块 :

>>> import operator
>>> operator.gt(2,1)
True


Answer 2:

__cmp__()是做的比较老式的方式,并支持丰富的运营商弃用 ( __lt____le__其只在Python 2.1引入等)。 有可能的转变是不完全的2.7.x的-而在Python 3.x的__cmp__被完全移除。

哈斯克尔拥有最优雅的实现我见过的-是一个Ord (有序)数据类型,你只需要定义如何<=的类型类本身的作品,并提供默认的实现为<= >>=来讲这两项(你很欢迎你来定义自己,如果你想要更多)。 你可以写这样的自己班在Python,不知道为什么,这不是默认的; 大概性能的原因。



Answer 3:

作为hircus表示, __cmp__风格比较是有利于丰富运营商的弃用 ( __lt__在Python 3,...)本来,比较使用实施__cmp__ ,但也有一些类型/情况下简单__cmp__运营商是不够的(一个Color类的实例如可以支持==!= ,但不<> ),所以加入了丰富的比较操作,留下__cmp__到位的向后兼容性。 继蟒蛇哲学“应该有one--和最好只有一个--obvious办法做到这一点,” 1传统支持是在Python 3去除,当向后兼容性可能被牺牲掉。

在Python 2,而int仍然使用__cmp__以免破坏向后兼容性,不是所有的浮点数是小于,大于,或等于其它浮点数(例如(float('nan') < 0.0, float('nan') == 0.0, float('nan') > 0.0)计算为(False, False, False) ,所以我应该float('nan').__cmp__(0.0)返回?),所以float使用需求较新的丰富的比较操作符。

1:尝试输入“进口这种”转换为Python外壳。



文章来源: Python: Why does the int class not have rich comparison operators like `__lt__()`?