Python namedtuple类上的自定义排序
我经常上课。我今天一直在想,是否有一种很好的方法来实现此类的自定义排序,即使默认排序键不是namedtuple的第一个元素(然后是第二个、第三个等) 我的第一反应是实施Python namedtuple类上的自定义排序,python,sorting,namedtuple,functools,Python,Sorting,Namedtuple,Functools,我经常上课。我今天一直在想,是否有一种很好的方法来实现此类的自定义排序,即使默认排序键不是namedtuple的第一个元素(然后是第二个、第三个等) 我的第一反应是实施\uu lt\uuuuuu和\uuuuu eq\uuuuuu,剩下的就让我去做(它填写了le、ne、gt、ge): 从集合导入namedtuple 从functools导入总排序 @总订单 B类(名称为双('B','x y')): 定义(自身、其他): 返回self.y
\uu lt\uuuuuu
和\uuuuu eq\uuuuuu
,剩下的就让我去做(它填写了le、ne、gt、ge):
从集合导入namedtuple
从functools导入总排序
@总订单
B类(名称为双('B','x y')):
定义(自身、其他):
返回self.y
然而:
def test_sortingB():
b1 = B(1, 2)
b2 = B(2, 1)
assert b2 < b1 # passes
assert b2 <= b1 # fails
def test_sortingB():
b1=B(1,2)
b2=B(2,1)
断言b2 assert b2我的建议是按照您希望字段排序的顺序创建namedtuple。您可能必须更改代码中创建值的部分(例如,将someTuple(“name”,24)
更改为someTuple(24,“name”)
,但通常情况下,创建值的位置比使用的位置少,因此这应该不是什么大问题。这避免了编写所有比较方法的麻烦,并且作为一个额外的好处,还避免了一直调用这些自定义比较方法所带来的额外性能开销。选项1.使用a并应用tota我想你会同意的
@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
@total\u排序
类别B_排序(对象):
__slots_uu=()#见雷蒙德的评论
定义(自身、其他):
返回self.y
选项2.根据total\u排序
创建您自己的装饰器,只需使用它即可如果,正如您的问题所暗示的,您的兴趣仅在于按备用键对名称进行排序,那么为什么不将sort/sorted键
参数与attrgetter
函数一起使用:
>>> from collections import namedtuple
>>> from operator import attrgetter
>>> P = namedtuple("P", "x y")
>>> p1 = P(1, 2)
>>> p2 = P(2, 1)
>>> sorted([p1, p2], key=attrgetter("y"))
[P(x=2, y=1), P(x=1, y=2)]
>>> from functools import partial
>>> sortony = partial(sorted, key=attrgetter("y"))
>>> sortony([p1, p2])
[P(x=2, y=1), P(x=1, y=2)]
您可以进一步定义自己的排序函数:
>>> from collections import namedtuple
>>> from operator import attrgetter
>>> P = namedtuple("P", "x y")
>>> p1 = P(1, 2)
>>> p2 = P(2, 1)
>>> sorted([p1, p2], key=attrgetter("y"))
[P(x=2, y=1), P(x=1, y=2)]
>>> from functools import partial
>>> sortony = partial(sorted, key=attrgetter("y"))
>>> sortony([p1, p2])
[P(x=2, y=1), P(x=1, y=2)]
你为什么不按照你想排序的顺序创建一个名元组呢?直到我已经创建了它并使用了一段时间,我才意识到我想要排序/最大化它。所以我现在可以添加一个前导字段作为排序字段,但这可能会有点混乱。但是你是如何使用名元组的呢?na的好处是medtuple允许您按名称访问项目,因此您可以更改namedtuple以使字段的顺序正确,并且不影响代码,只要您按名称访问字段(可能是这样做的,或者为什么使用namedtuple?)。是的,在访问字段时,我使用名称,但在初始化字段时通常不使用名称(请参阅我在问题第3页的评论)。排序字段还不存在,因此我需要添加它,或者使用一个cmp方法来查看2个字段并对其进行一些逻辑处理。(我的示例代码过于简化)选项1和选项2的开销是否有显著差异?+1。选项1直接解决了总排序问题,只填充缺失的值。@选项1的开销是否接近零(方法解析顺序中的一个额外步骤)。@Johnlaroy,我建议添加u slots uu=()请选择1以恢复内存效率。