Is there a possibility to create any python object that will be not sortable? So that will be an exception when trying to sort a list of that objects? I created a very simple class, didn't define any comparison methods, but still instances of this class are comparable and thus sortable. Maybe, my class inherits comparison methods from somewhere. But I don't want this behaviour.
You could define a __cmp__ method on the class and always raise an exception when it is called. That might do the trick.
Out of curiosity, why?
Why don't you just write a class that contains a list object and provides methods to access the data inside? By doing that you would effectively hide the list and therefore prevent them from sorting it.
As Will McCutchen has mentioned, you can define a __cmp__ method that raises an exception to prevent garden variety sorting. Something like this:
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
However, you cannot truly prevent a developer from sorting a list of your objects. Using the key or cmp argument with list.sort() or with the built-in standalone sorted() function , anyone can circumvent the __cmp__ method by using a custom comparison function or sorting key.
# 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>]
As others will point out, I'm not sure there's much value in trying to prevent someone from sorting an object. If this isn't just a curious itch you're trying to scratch, what's the use case for this?
The default list sorting uses the built-in cmp() function on its elements. The cmp() function checks if its arguments (2 elements from your list) have a __cmp__() method. If yes, this method is used for comparison. Otherwise, as in your case, the argument object IDs (return value of the built-in function id()) are used for comparison.
To let the sorting fail, you could define a comparison method which throws an Exception:
>>> 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
Sets don't have a total ordering
>>> s=set((1,2,3))
>>> t=set("abc")
>>> s<t
False
>>> t<s
False
>>>
But no exception is raise when you try to sort them
>>> sorted([s,t])
[set([1, 2, 3]), set(['a', 'c', 'b'])]
For what it's worth, in Python 3 the default will be for new items to not be comparable (and hence not sortable). In Python 2, you have to explicitly create a __cmp__ or __lt__ method, as others have said.
The python sort algorithms use the __lt__ special method. Keeping in mind that using the cmp and key arguments of the sorting function and methods, it is suggested that your class defines a method:
def __lt__(self, other):
raise NotImplementedError