繁体   English   中英

在python中对类实例进行排序

[英]Sorting class instances in python

python 2.7用于排序vanilla类实例的是什么? 我对默认排序行为感兴趣。

假设我有班级

class S():
    pass

然后我可以创建几个实例,并对它们进行排序:

a = S(); b = S(); c = S()
l = [(a,'a'), (b,'b') ,(c, 'c')]
sorted(l)

这将打印一些对象的排序。 现在我有两个问题:

  • python使用对象' __hash__() ,因此他们的id()
  • 是否可以覆盖__hash__()来影响排序行为?

Python 3的内置排序使用了类中的__lt__方法。

丰富的比较方法在Python中很特殊,因为如果没有定义__lt__ ,它们可以返回一个特殊的NotImplemented类型 - 看看这个页面上的文档: http__lt__ 该标准型的层次结构

由于NotImplemented的真值是True ,任何得到NotImplemented布尔比较都将继续,就好像第一个元素实际上小于第二个元素一样,这将导致排序按照与原来相同的顺序离开列表。

看一下交互式shell。 您可以看到如何在排序中使用真值,并且Python认为两个对象都小于彼此:

>>> class S():
...     pass
...
>>> a = S()
>>> b = S()
>>> a.__lt__( b )
NotImplemented
>>> if a.__lt__( b ):
...     print( "derp!" )
...
derp
>>> if b.__lt__(a):
...     print( "derp" )
...
derp

以下是一些参考资料:

编辑:看了Python 2.7之后,它看起来像对象的ID用于排序,并且__lt__方法在像你的例子这样的简单类上是未定义的。 对不起任何困惑。

Python的排序算法使用“小于”测试专门比较项目,这可以使用类上的__cmp__()特殊方法(现已弃用)或__lt__()来实现。

在没有关于如何比较两个对象的任何特定指令的情况下,对于相同类型的对象,使用id() (而不是哈希),就像在您的情况下一样。

我在自己的机器上尝试了你的例子(python 2.7):

>>> sorted(l)
[(<__main__.S instance at 0x107142a70>, 'a'), (<__main__.S instance at 0x107142ab8>, 'b'), (<__main__.S instance at 0x107142b00>, 'c')]

请注意,排序列表按id()顺序排列:

>>> id(a)
4413729392
>>> id(b)
4413729464
>>> id(c)
4413729536

如果我生成哈希,我得到:

>>> hash(a)
275858087
>>> hash(b)
-9223372036578917717
>>> hash(c)
275858096

这表明排序不是基于哈希。

有关如何使python按照您的方式对您的类进行排序的信息,请参阅derekerdmann的答案。

编辑:顺便说一句,如果您将项目反向放入列表然后对其进行排序,您会得到:

>>> l = [(c,'c'), (b, 'b'), (a, 'a')]
>>> sorted(l)
[(<__main__.S instance at 0x107142a70>, 'a'), (<__main__.S instance at 0x107142ab8>, 'b'), (<__main__.S instance at 0x107142b00>, 'c')]

再一次,它按id()顺序排序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM