I use namedtuple classes a lot. I have been thinking today if there is a nice way to implement custom sorting for such a class, i.e. make the default sort key not the first element (then second, third, etc) of the namedtuple.
My first instinct was to implement __lt__
and __eq__
and let total_ordering
do the rest (it fills out le, ne, gt, ge):
from collections import namedtuple
from functools import total_ordering
@total_ordering
class B(namedtuple('B', 'x y')):
def __lt__(self, other):
return self.y < other.y
However:
def test_sortingB():
b1 = B(1, 2)
b2 = B(2, 1)
assert b2 < b1 # passes
assert b2 <= b1 # fails
oh, right... total_ordering
only fills out the other methods if they are missing. Since tuple/namedtuple has such methods, total_ordering isn't doing anything for me.
So I guess my options are
Suggestions on the best way to solve this?
OPTION 1. Use a mixin and apply the total_ordering to that
@total_ordering
class B_ordering(object):
__slots__ = () # see Raymond's comment
def __lt__(self, other):
return self.y < other.y
class B(B_ordering, namedtuple('B', 'x y')):
pass
OPTION 2. Make your own decorator based on total_ordering
and just use that instead
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With