對象包含的內置方法
class MyObj(object):
def __init__(self):
self.value = 0
myObj = MyObj()
print(dir(myObj))
返回結果
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'value']
其中和對象比較的內置方法包括:
['__eq__', '__ge__', '__gt__', '__le__', '__lt__', '__ne__']
所以要重寫對象的比較規則,需要重寫這些比較方法。這樣寫很簡單,挨個實現就可以了。但是好事者高出了更吊的方法:@functools.total_ordering
源代碼如下:
_convert = {
'__lt__': [('__gt__', _gt_from_lt),
('__le__', _le_from_lt),
('__ge__', _ge_from_lt)],
'__le__': [('__ge__', _ge_from_le),
('__lt__', _lt_from_le),
('__gt__', _gt_from_le)],
'__gt__': [('__lt__', _lt_from_gt),
('__ge__', _ge_from_gt),
('__le__', _le_from_gt)],
'__ge__': [('__le__', _le_from_ge),
('__gt__', _gt_from_ge),
('__lt__', _lt_from_ge)]
}
def total_ordering(cls):
"""Class decorator that fills in missing ordering methods"""
# Find user-defined comparisons (not those inherited from object).
roots = [op for op in _convert if getattr(cls, op, None) is not getattr(object, op, None)]
if not roots:
raise ValueError('must define at least one ordering operation: < > <= >=')
root = max(roots) # prefer __lt__ to __le__ to __gt__ to __ge__
for opname, opfunc in _convert[root]:
if opname not in roots:
opfunc.__name__ = opname
setattr(cls, opname, opfunc)
return cls
這樣一來,只要你在定義class的時候加上這個注解,再重寫運算符的時候,除了 __eq__
和__ne__
之外,其他的4個只需要重寫一個就可以了,@functools.total_ordering直接就幫你完成了其他比較方法的重寫。
@functools.total_ordering
class MyObj(object):
def __init__(self):
self.value = 0
def __eq__(self, other):
self