Что я делаю неправильно (реализация альтернативного равенства с перегрузкой в python)

1

Человек задал вопрос о том, как получить уникальную функцию списка в python с альтернативной функцией равенства.

Я думал, что это можно сделать, наследуя класс элемента и перегружая функцию равенства

import functools
@functools.total_ordering
class ffloat(float):
def __eq__(self,other):
    if floor(self) == floor(other):
        return True
    else:
        return False
def __le__(self,other):
    if self == other:
        return True
    else:
        return float(self) <= float(other)
def __hash__(self):
    return floor(self)


a = map(ffloat,[4.3,8,8.9, 13])


In [41]: a[1] == a[2]
Out[41]: True

но

In [42]: set(a)
Out[42]: set([4.3, 8.0, 8.9, 13.0])

Изменение: заменить abs <1.5 равенство с равенством пола
Добавленный Hash PS - это способ сделать из этого класса класс, что класс и две лямбда и возвращают класс, который наследует от первого, переопределяя необходимую функцию равенства.

  • 0
    (PSST)
Теги:
wrapper
equality

1 ответ

8
Лучший ответ

Это не действительная функция равенства, так как она не транзитивна:

mfloat(0) == mfloat(1) == mfloat(2), но mfloat(0) != mfloat(2).

Также обратите внимание, что для использования в наборе вы должны переопределить __hash__ чтобы для всех экземпляров a, b вашего класса __hash__ следующее свойство:

a == b ⇒ hash(a) == hash(b)

set обнаруживает, что hash(mfloat(8)) != hash(mfloat(9)). Так как множество предполагает, что указанное свойство имеет место, он заключает, что mfloat(8) != mfloat(9) без фактического вызова __eq__.


Таким образом, это работает:
from math import floor
class ffloat(float):
    def __eq__(self,other):
        return floor(self) == floor(other):
    def __hash__(self):
        return floor(self)

a = map(ffloat,[4.3,8,8.9, 13])
print(set(a))
# output: {8.0, 4.3, 13.0}
  • 0
    Это хороший момент. Я сделал это для равенства полов и получил те же результаты.
  • 0
    @Roman A. Taycher Равенство полов ( __eq__ = lambda x,y: floor(x) = floor(y) ) является переходным. Вы, вероятно, забыли реализовать __hash__ = lambda self: floor(self) .
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню