Python допускает выражения типа x > y > z
, который, согласно документам, эквивалентен (x > y) and (y > z)
, за исключением того, что y
оценивается только один раз. (https://docs.python.org/3/reference/expressions.html)
Однако это, похоже, нарушается, если я настраиваю функции сравнения. Например. предположим, что у меня есть следующий класс: (Извинения за большой блок, но как только вы читаете метод __eq__
, остальное тривиально.)
class CompareList(list):
def __repr__(self):
return "CompareList([" + ",".join(str(x) for x in self) + "])"
def __eq__(self, other):
if isinstance(other, list):
return CompareList(self[idx] == other[idx] for idx in xrange(len(self)))
else:
return CompareList(x == other for x in self)
def __ne__(self, other):
if isinstance(other, list):
return CompareList(self[idx] != other[idx] for idx in xrange(len(self)))
else:
return CompareList(x != other for x in self)
def __gt__(self, other):
if isinstance(other, list):
return CompareList(self[idx] > other[idx] for idx in xrange(len(self)))
else:
return CompareList(x > other for x in self)
def __ge__(self, other):
if isinstance(other, list):
return CompareList(self[idx] >= other[idx] for idx in xrange(len(self)))
else:
return CompareList(x >= other for x in self)
def __lt__(self, other):
if isinstance(other, list):
return CompareList(self[idx] < other[idx] for idx in xrange(len(self)))
else:
return CompareList(x < other for x in self)
def __le__(self, other):
if isinstance(other, list):
return CompareList(self[idx] <= other[idx] for idx in xrange(len(self)))
else:
return CompareList(x <= other for x in self)
Теперь я могу делать такие забавные вещи, как CompareList([10, 5]) > CompareList([5, 10])
, и он будет правильно возвращать CompareList([True,False])
Однако цепочки этих операций не работают красиво:
low = CompareList([1])
high = CompareList([2])
print(low > high > low) # returns CompareList([True])
Почему бы и нет? Что происходит под капотом здесь? Я знаю, что это не эквивалентно (low > high) > low
= (False > low)
(потому что это вернет False). Это может быть low > (high > low)
, но это не имеет смысла с точки зрения приоритета оператора (обычно слева направо).