在namedtuple类上自定义排序

pfc*_*ise 7 python sorting namedtuple functools

经常使用namedtuple类.我一直在想今天是否有一种很好的方法来为这样的类实现自定义排序,即使默认排序键不是namedtuple的第一个元素(然后是第二个,第三个等).

我的第一直觉是实现__lt____eq__total_ordering剩下的工作完成(它填写了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
Run Code Online (Sandbox Code Playgroud)

然而:

def test_sortingB():
    b1 = B(1, 2)
    b2 = B(2, 1)
    assert b2 < b1  # passes
    assert b2 <= b1  # fails
Run Code Online (Sandbox Code Playgroud)

哦,对...... 如果缺少total_ordering其他方法,则只填写其他方法.由于tuple/namedtuple有这样的方法,total_ordering对我没有任何作用.

所以我想我的选择是

  1. 停止使用namedtuple并构建我自己的无聊类,继续使用total_ordering
  2. 继续使用namedtuple并实现所有6种比较方法
  3. 继续使用namedtuple并插入排序值作为第一个字段.幸运的是,我没有太多的课程实例,但通常我只是依靠字段的顺序来初始化它们,这可能是令人讨厌的.也许这是一个坏习惯.

关于解决这个问题的最佳方法的建议?

Joh*_*ooy 13

选项1.使用mixin并对其应用total_ordering

@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
Run Code Online (Sandbox Code Playgroud)

选项2.制作自己的装饰器,total_ordering然后使用它