jis*_*one 21 python language-design language-history
非常好奇.
我已经注意到了(至少在PY 2.6和2.7),一个float拥有所有熟悉的丰富的比较函数:__lt__(),__gt__,__eq__等.
>>> (5.0).__gt__(4.5)
True
Run Code Online (Sandbox Code Playgroud)
但是int没有
>>> (5).__gt__(4)
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: 'int' object has no attribute '__gt__'
Run Code Online (Sandbox Code Playgroud)
这对我来说很奇怪,因为运营商本身运作良好
>>> 5 > 4
True
Run Code Online (Sandbox Code Playgroud)
甚至字符串也支持比较功能
>>> "hat".__gt__("ace")
True
Run Code Online (Sandbox Code Playgroud)
但所有的int都是__cmp__()
对我来说似乎很奇怪,所以我想知道为什么会这样.
刚刚测试过,它在python 3中按预期工作,所以我假设有一些遗留原因.仍然希望听到正确的解释;)
Dav*_*ebb 21
如果我们查看PEP 207 for Rich 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);
}
Run Code Online (Sandbox Code Playgroud)
因此,似乎在2.x中存在一个现有的性能优化 - 通过允许C代码直接比较整数 - 如果已经实现了丰富的比较运算符,则不会保留这些整数.
现在__cmp__不再支持Python 3,因此必须有丰富的比较运算符.据我所知,现在这不会导致性能下降.例如,比较:
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
Run Code Online (Sandbox Code Playgroud)
至:
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
Run Code Online (Sandbox Code Playgroud)
所以似乎有类似的优化,但我的猜测是判断调用是将它们全部放在2.x分支中,当向后兼容性是一个考虑时,这将是一个太大的变化.
在2.x中如果你想要丰富的比较方法,你可以通过operator模块得到它们:
>>> import operator
>>> operator.gt(2,1)
True
Run Code Online (Sandbox Code Playgroud)
__cmp__()是做的比较老式的方式,并支持丰富的运营商弃用(__lt__,__le__其中只在Python 2.1引入等).可能从2.7.x开始过渡并不完整 - 而在Python 3.x __cmp__中完全删除了.
Haskell拥有我见过的最优雅的实现 - 成为Ord(序数)数据类型,你只需要定义如何<和=工作,类型类本身提供默认实现<=,>并且>=就这两者而言(你是如果你愿意,欢迎定义自己).您可以在Python中自己编写这样的类,但不确定为什么不是默认类; 可能性能原因.
| 归档时间: |
|
| 查看次数: |
1318 次 |
| 最近记录: |