晴好奇。
我已经注意到了(至少在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如预期,所以我假定一些遗留的原因。 还是想听到一个适当的解释,虽然;)
如果我们看一下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
__cmp__()
是做的比较老式的方式,并支持丰富的运营商弃用 ( __lt__
, __le__
其只在Python 2.1引入等)。 有可能的转变是不完全的2.7.x的-而在Python 3.x的__cmp__
被完全移除。
哈斯克尔拥有最优雅的实现我见过的-是一个Ord
(有序)数据类型,你只需要定义如何<
和=
的类型类本身的作品,并提供默认的实现为<=
>
和>=
来讲这两项(你很欢迎你来定义自己,如果你想要更多)。 你可以写这样的自己班在Python,不知道为什么,这不是默认的; 大概性能的原因。
作为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__()`?