自定义类排序:没有抛出错误,Python测试的目的是什么?
在没有指定对象的相等比较属性的情况下,Python在使用自定义类排序:没有抛出错误,Python测试的目的是什么?,python,object,python-2.x,comparison-operators,Python,Object,Python 2.x,Comparison Operators,在没有指定对象的相等比较属性的情况下,Python在使用和编辑时仍然在做一些事情:阅读后查看更新!完全正确的答案是“未定义,但一致” 它测试的是repr(me)vsrepr(you),本质上就是做字符串比较。下面是一个容易看到的示例: class A(object): pass class B(object): pass x = A() # <__main__.A object at 0x7f7014e4e2d0> y = B() # <__main__.B object
和编辑时仍然在做一些事情:阅读后查看更新!完全正确的答案是“未定义,但一致”
它测试的是repr(me)
vsrepr(you)
,本质上就是做字符串比较。下面是一个容易看到的示例:
class A(object): pass
class B(object): pass
x = A() # <__main__.A object at 0x7f7014e4e2d0>
y = B() # <__main__.B object at 0x7f7014e4e310>
z = A() # <__main__.A object at 0x7f7014e4e390>
x < z < y # True (assuming that the memory addresses are ordered as above)
A类(对象):通过
B类(对象):通过
x=A()#
y=B()#
z=A()
x
我同意这对我来说有点奇怪。也许有一个我不知道的很好的理由
更新:我对repr
的看法是错误的,尽管它看起来确实在测试中使用了基本对象
repr
其中有一行说明“一个对象被视为比另一个对象小还是大的选择是任意的,但在程序的一次执行中是一致的。”换句话说,它可能使用repr
,但这不能保证。但是,这将是一致的。如果没有丰富的比较运算符,Python将使用对象的repr()
。(至少,这对Py2有效;我不知道对Py3有效)
所以如果你这样做了
class A(object): pass
class B(object): pass
l = [A() if i % 2 else B() for i in range(1000)]
l.sort()
对象按其repr()
进行排序,A()
排在第一位,然后是B()
对对象施加任意顺序。排序仅定义为
这意味着在比较任意对象时,由Python实现定义顺序。如果类型相同,则CPython使用内存地址(从中):
在上面的例子中,它使用的是repr
,而不是id
。是的,它不是对象id,我已经测试过了。关于repr
测试的任何参考资料?有相关文档吗?这显然是错误的。带有\uuuu repr\uuuu()钩子的自定义类不能通过为repr(实例)
返回不同的值来改变它们的顺序。因此,没有任何迹象表明repr
参与了排序。好吧,这有点随机?这对我来说似乎很危险,也没有必要。为什么不像其他相等操作一样抛出一个错误呢?好的,那么这就是要比较的内存地址的字符串表示形式?i、 e.0x162afd0
vs0x162afd0
@ravidicus:正在比较的是实际内存地址。默认的repr()
返回值包含内存地址的十六进制表示,但这不是用于比较的。例如,您可以提供一个自定义的\uuu repr\uuu()
钩子,它不会改变顺序(或内存地址)。@如果类是同一类型,它将使用内存。Martijn的回答很好,比我的回答更彻底。明白了。谢谢,我将把这个标记为已接受。但我还是不喜欢也不理解其中的逻辑@爬行动物:逻辑是这是一个错误,现在它在py3k中被修复了。
class A(object): pass
class B(object): pass
l = [A() if i % 2 else B() for i in range(1000)]
l.sort()
if (v->ob_type == w->ob_type) {
/* When comparing these pointers, they must be cast to
* integer types (i.e. Py_uintptr_t, our spelling of C9X's
* uintptr_t). ANSI specifies that pointer compares other
* than == and != to non-related structures are undefined.
*/
Py_uintptr_t vv = (Py_uintptr_t)v;
Py_uintptr_t ww = (Py_uintptr_t)w;
return (vv < ww) ? -1 : (vv > ww) ? 1 : 0;
}
>>> class Foo(): pass
...
>>> Foo() < Foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: Foo() < Foo()