Python:默认比较

10 投票
3 回答
4958 浏览
提问于 2025-04-16 19:01

在Python 2.7中,我定义了一个空的新式类:

In [43]: class C(object): pass
   ....:

然后我创建了这个新类的实例列表:

In [44]: c = [C() for i in xrange(10)]

接着我尝试对这个列表进行排序:

In [45]: sorted(c)
Out[45]:
[<__main__.C object at 0x1950a490>,
 <__main__.C object at 0x1950a4d0>,
 ...
 <__main__.C object at 0x1950aad0>]

令人惊讶的是,排序并没有报错,尽管我并没有定义如何比较这个类的实例C

In [46]: dir(C())
Out[46]:
['__class__',
 '__delattr__',
 '__dict__',
 '__doc__',
 '__format__',
 '__getattribute__',
 '__hash__',
 '__init__',
 '__module__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__']

那么,这到底发生了什么呢?这种行为的原因是什么呢?

3 个回答

0

看看你打印出来的值。注意“Object C at”旁边的那个十六进制数字吗?那是一个指针引用。简单来说,它可以大致理解为创建的顺序。如果你遍历那个列表,你会发现它是根据这个顺序来排序对象的。

顺便提一下,我记得我曾经对Python 2.x的比较感到困惑……不过我不确定这个问题在Python 3中是否解决了。

1

我不是很确定,但也许有人可以纠正我。

当你比较对象时,其实是在比较它们在内存中的地址,就像在C语言中比较两个字符串一样。如果你仔细看看,排序是把对象从内存地址最低的排到最高的(或者说是指针的位置)。

16

我觉得这样做的唯一理由是,方便对象可以被排序,并且可以用作字典的键,具有一些默认的行为。相关的内容可以在这个语言定义的章节找到:https://docs.python.org/2/reference/expressions.html#not-in

“判断一个对象是否比另一个对象小或大,这个选择是随意的,但在程序执行的过程中是保持一致的。”

所以,目前对象是通过内存地址来比较的这个事实,只是一个实现细节,并不能完全依赖。唯一可以保证的是,在执行过程中,排序的顺序是保持一致的。

撰写回答