8

>在不指定对象的相等比较属性的情况下,Python 在使用and时仍然在做一些事情<。如果您不指定__gt__or ,Python 实际比较这些对象的依据是什么__lt__?我预计这里会出现不支持的操作数错误,就像您在尝试将两个对象相加而不使用 defing 时遇到的那样__add__


In [1]: class MyObject(object):
   ...:     pass
   ...: 
In [2]: class YourObject(object):
   ...:     pass
   ...: 
In [3]: me = MyObject()
In [4]: you = YourObject()
In [5]: me > you
Out[5]: False
In [6]: you > me
Out[6]: True

4

3 回答 3

6

对对象施加任意顺序。排序仅被定义为在程序执行中是稳定的

这意味着在比较任意对象时由 Python 实现定义排序。如果类型相同,CPython 使用内存地址(来自C 源):

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;
}

相同的值是id()函数的基础,并且在自定义类的默认字符串中也表示repr(),因此看起来repr()的 确定顺序。它只是内存地址。

对于不同类型的对象,使用类型名称来代替(类似数字的类型在其他类型之前排序),如果类型不同但名称相同,则代码回退到类型的内存地址(与类型相同时实例的内存地址相反)。

这种隐式排序被认为是语言中的错误,并已在 Python 3 中得到纠正

当操作数没有有意义的自然排序时,排序比较运算符 ( <, <=, >=, >) 会引发异常。TypeError

这适用于没有实现必要的排序钩子的自定义类:

>>> class Foo(): pass
... 
>>> Foo() < Foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: Foo() < Foo()
于 2012-11-19T15:51:13.047 回答
4

编辑:阅读后查看更新!完全正确的答案是“未定义,但一致”。

它是测试repr(me)repr(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)

我同意这对我来说有点奇怪。也许有一个我不知道的充分理由?

更新:我错了repr,尽管它看起来确实object在测试中使用了基础 repr。http://docs.python.org/2/reference/expressions.html#not-in

那里有一行写着“一个对象被认为比另一个对象更小还是更大的选择是在程序的一次执行中任意但始终如一地做出的。” 换句话说,它可能正在使用repr,但不能保证。但是,它将始终如一地进行。

于 2012-11-19T15:31:00.307 回答
0

repr()如果没有丰富的比较运算符,Python 会使用该对象的。(至少,这对 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()

于 2012-11-19T15:31:25.020 回答