在实现类的__eq__
和__lt__
方法时,通常的做法是使用元组对要比较的值进行分组,如下所示:
@total_ordering
class Foo(object):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def __hash__(self):
return hash((self.c, self.a, self.b))
def __eq__(self, other):
return (self.c, self.a, self.b) == (other.c, other.a, other.b)
def __lt__(self, other):
return (self.c, self.a, self.b) < (other.c, other.a, other.b)
然而,这使用每个键的自然顺序。如果我想更改,例如a
如何排序?
这是我到目前为止所提出的,虽然看起来工作正常,但我想知道是否有更好的方法可以解决这个问题:
@total_ordering
class Foo(object):
def __init__(self, a, b, c):
self.a = MyA(a) # Note
self.b = b
self.c = c
def __hash__(self):
return hash((self.c, self.a, self.b))
def __eq__(self, other):
return (self.c, self.a, self.b) == (other.c, other.a, other.b)
def __lt__(self, other):
return (self.c, self.a, self.b) < (other.c, other.a, other.b)
class MyA(A):
def __hash__(self):
# ...
def __eq__(self, other):
# ...
def __lt__(self, other):
# ...
子类化A
让我可以定义我的自定义排序,并允许MyA
以其他方式表现得像常规A
这样很好,但它似乎很浪费/不必要地冗长,特别是如果我必须为多个领域这样做。
编辑:根据用户1320237的回答,这就是我的想法:
@total_ordering
class Foo(object):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def __hash__(self):
return hash((self.c, self.a, self.b))
def __eq__(self, other):
return (0, 0, 0) == (cmp(self.c, other.c),
cmpA(self.a, other.a),
cmp(self.b, other.b))
def __lt__(self, other):
return (0, 0, 0) > (cmp(self.c, other.c),
cmpA(self.a, other.a),
cmp(self.b, other.b))
def cmpA(a1, a2):
# ...
(注意>
中的__lt__
cmp(x, y)
,-1
如果x < y
和__lt__
返回True
则返回{{1}}} < / p>
答案 0 :(得分:2)
如果你想用list.sort()订购,例如你可以传递参数:
您的代码:
...
def __lt__(self, other):
return (self.c, self.a, self.b) < (other.c, other.a, other.b)
...
list.sort()
当量:
list.sort(key = lambda self: (self.c, self.a, self.b))
也等同于:
list.sort(cmp = lambda self, other: \
(self.c, self.a, self.b) < (other.c, other.a, other.b))
所以,如果你想以不同的方式对你的答案进行排序,我建议:
class Foo(object):
@staticmethod
def cmp_absoluteOrder(self, other):
return (self.c, self.a, self.b) < (other.c, other.a, other.b)
@staticmethod
def cmp_otherOrder(self, other):
return ...
@staticmethod
def cmp_combinedSort(cmpA, cmpB, cmpC):
return lambda self, other: (0, 0, 0) < (cmpA(self.c, other.c), cmpA(self.a, other.a), cmpA(self.b, other.b), )
def __hash__(self):
return hash(self.c) ^ hashA(self.a) ^ hash(self.b)
...
list.sort(cmp = Foo.cmp_absoluteSorting)
list.sort(cmp = Foo.cmp_combinedSort(cmp, (lambda a1, a2: ...), cmp))
hashA = hash # or replace it if important # but the same a will retunrn the same hash
或类似的东西
答案 1 :(得分:1)
如果这只是一次性动作,可以使用以下内容:
def custom_sorter(foo):
"""Takes Foo objects and gives a representation for sorting."""
return (foo.c, A(foo.a), foo.b)
sorted(foo_list, key=custom_sorter)
如果要多次完成,您可以考虑在Foo
上使用可扩展的类方法并吐出类似于custom_sorter
的原型。
如果您多次使用相同自定义排序器,为什么不将它作为课程的一部分呢?
你真的只需要问自己为什么和我真的需要。