Имеет смысл проверять на идентификационные данные в __ eq __?

Когда реализация пользовательского равенства функционирует для класса, имеет смысл проверять на идентификационные данные сначала? Пример:

def __eq__(self, other):
    return (self is other) or (other criteria)

Это интересное для случаев, когда другие критерии могут быть более дорогими (например, сравнение некоторых длинных строк).

8
задан Björn Pollex 5 July 2010 в 14:00
поделиться

5 ответов

необходимо: нет

это делает смысл: конечно, а почему бы и нет?

По умолчанию такая проверка не выполняется, как вы можете видеть здесь:

class bad(object):
    def __eq__(self, other):
        return False

x = bad()
print x is x, x==x # True, False
3
ответ дан 5 December 2019 в 12:54
поделиться

Это может быть совершенно разумным сокращением для проверки тождества сначала, и в методах равенства хорошие сокращения (как для равенства, так и для неравенства) - это то, что вы должны искать, чтобы вы могли вернуться как можно быстрее.

Но, с другой стороны, это может быть и совершенно лишней проверкой, если ваш тест на равенство в остальном дешев, а на практике вы вряд ли будете сравнивать объект с самим собой.

Например, если равенство между объектами можно определить, сравнивая одно или два целых числа, то это должно быть быстрее, чем проверка на тождество, так что меньше, чем за время, необходимое для сравнения ids, вы получите весь ответ. И помните, что если вы проверяете тождества, а объекты не имеют одинаковых id (что вероятно в большинстве сценариев), то вы ничего не получили, так как вам все равно придется выполнять полную проверку.

Таким образом, если полная проверка равенства стоит недешево и есть вероятность, что объект может быть сравнен сам с собой, то проверка идентичности вначале может быть хорошей идеей.


Обратите внимание, что еще одна причина, по которой проверка не выполняется по умолчанию, заключается в том, что вполне разумно (хотя и редко) объекты с одинаковыми идентификаторами сравнивать как неравные, например:

>>> s = float('nan')
>>> s == s
False
7
ответ дан 5 December 2019 в 12:54
поделиться

Когда вы реализуете пользовательское равенство в классе, вы можете решить для себя, проверять ли в первую очередь идентификацию. Все зависит от вас. Обратите внимание, что в Python также вполне допустимо решить, что __ eq __ и __ ne __ вернут одно и то же значение для данного аргумента; так что можно определить равенство таким образом, чтобы идентичность не была сокращением.

Это, безусловно, улучшение скорости, хотя насколько сильно зависит от сложности метода. Обычно я не беспокоюсь о своих пользовательских классах, но у меня не так много кода, критичного к скорости (и там, где я его делаю, сравнение объектов не является горячей точкой).

Для большинства моих объектов метод равенства выглядит так:

def __eq__(self, o):
    try:
        return self.x == o.x and self.y == o.y
    except AttributeError:
        return False

Я мог бы легко добавить проверку , если self равно o: return True в начале метода.

Также не забудьте переопределить __ hash __ , если вы переопределите __ eq __ , иначе вы получите странное поведение в set s и dict s .

2
ответ дан 5 December 2019 в 12:54
поделиться

Я задавал подобный вопрос на comp.lang.python несколько лет назад - вот эта тема. Тогда были сделаны выводы, что предварительный тест на идентичность стоит того, если вы делаете много тестов на равенство объектов самим себе, или если ваша другая логика тестирования равенства медленная.

1
ответ дан 5 December 2019 в 12:54
поделиться

Это делается только из соображений производительности.

На одной работе по программированию, на которой я работал, в Java это всегда делалось, хотя это не меняет никакой функциональности.

0
ответ дан 5 December 2019 в 12:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: