有没有办法创建一个不可排序的python对象?

时间:2010-03-02 21:55:28

标签: python

是否有可能创建任何不可排序的python对象?那么在尝试对这些对象列表进行排序时会出现异常吗? 我创建了一个非常简单的类,没有定义任何比较方法,但是这个类的实例仍然具有可比性,因此可以排序。也许,我的类从某个地方继承了比较方法。但我不想要这种行为。

7 个答案:

答案 0 :(得分:7)

您可以在类上定义__cmp__方法,并在调用时始终引发异常。这可能会成功。

出于好奇,为什么?

答案 1 :(得分:1)

正如Will McCutchen所提到的,您可以定义一个__cmp__方法,该方法会引发异常以防止花园种类排序。像这样:

class Foo(object):
    def __cmp__(self, other):
        raise Exception()

a = [Foo(), Foo(), Foo()]
a.sort()
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 3, in __cmp__
Exception

但是,您无法真正阻止开发人员对对象列表进行排序。使用keycmp参数与list.sort()或内置的独立sorted()函数,任何人都可以通过使用自定义比较函数绕过__cmp__方法或排序键。

# continuing from above
>>> a = [Foo(), Foo(), Foo()]
>>> a
[<__main__.Foo object at 0x1004a3350>, <__main__.Foo object at 0x1004a3390>,
 <__main__.Foo object at 0x1004a33d0>]

>>> a.sort(key=id, reverse=True)
>>> # or a.sort(cmp=lambda a, b: cmp(id(b), id(a)))
>>> # or sorted(a, key=id)
>>> # etc...
[<__main__.Foo object at 0x1004a33d0>, <__main__.Foo object at 0x1004a3390>,
 <__main__.Foo object at 0x1004a3350>]

正如其他人会指出的那样,我不确定试图阻止某人对某个对象进行排序有多大价值。如果这不只是一个奇怪的痒,你试图划伤,这是什么用例?

答案 2 :(得分:1)

默认列表排序在其元素上使用内置的cmp()函数。 cmp()函数检查其参数(列表中的2个元素)是否具有__cmp__()方法。如果是,则使用此方法进行比较。否则,就像你的情况一样,参数对象ID(内置函数id()的返回值)用于比较。

要让排序失败,您可以定义一个抛出异常的比较方法:

>>> class X(object):
...    def __cmp__(self, other):
...        raise StandardError # or whatever Exception you need
...
>>> l = [X(), X(), X()]
>>> l.sort()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in __cmp__
StandardError

答案 3 :(得分:1)

对于它的价值,在Python 3中,默认将是新项目无法比较(因此不可排序)。在Python 2中,您必须明确地创建__cmp____lt__方法,正如其他人所说的那样。

答案 4 :(得分:0)

为什么不编写一个包含列表对象的类并提供访问内部数据的方法?通过这样做,您将有效地隐藏列表,从而阻止它们对其进行排序。

答案 5 :(得分:0)

集合没有总排序

>>> s=set((1,2,3))
>>> t=set("abc")
>>> s<t
False
>>> t<s
False
>>> 

但是,当您尝试对它们进行排序时,不会出现异常

>>> sorted([s,t])
[set([1, 2, 3]), set(['a', 'c', 'b'])]

答案 6 :(得分:0)

python排序算法使用__lt__特殊方法。请记住,使用排序函数和方法的cmpkey参数,建议您的类定义一个方法:

def __lt__(self, other):
    raise NotImplementedError