1

This is surely a duplicate, but say I have a class as follows:

class MyObj(object):
    def __init__(self, *args, **kwargs):
        self._data = [2, 1, 3]
        self._more_data = [False, True, False]

How can I make it sortable, not against other MyObj objects (which I could do with __lt__), but internally? So if I call sorted(my_obj_instance) I get a version with data like:

self._data = [1,2,3]
self._more_data [True, False, False]

That is, _data is sorted numerically, and _more_data has been sorted correspondingly.

mlissner
  • 17,359
  • 18
  • 106
  • 169

3 Answers3

5

sorted() never modifies the original data. To make it work with a custom object you'd have to implement __iter__ though (returning e.g. iter(self._data)) - but that would just give you a sorted version of that object and neither modify your original object nor sort both lists.

What you want is a sort() method which you'd call as yourobj.sort(). This method would then call .sort() on the lists with an appropriate key argument for the way you want them sorted.

ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
  • 1
    If "sorted" order is more important - then I'm wondering if the OP should re-consider the data structure and keep those items in something else..., but yeah +1 – Jon Clements Jun 06 '13 at 06:29
  • Yeah, the example is just to make the need for a custom sort method clear, thanks. – mlissner Jun 06 '13 at 15:41
3

You can't make sorted return an instance of your class. sorted always returns a list. If you make it an iterator you can get sorted to return a sorted version of your class's data (as a list). But it's probably simpler to just give your class a method called sort that sorts its data.

Community
  • 1
  • 1
BrenBarn
  • 242,874
  • 37
  • 412
  • 384
3

You can define a sort method like this

def sort(self)
    self._data, self._more_data = zip(*sorted(zip(self._data, self._more_data)))

This zips the two attributes into 2-tuples. Does the sort over the list of 2-tuples and unzips them again.

John La Rooy
  • 295,403
  • 53
  • 369
  • 502