Имеет ли смысл проверять личность в __eq__? - PullRequest
8 голосов
/ 05 июля 2010

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

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

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

Ответы [ 5 ]

7 голосов
/ 05 июля 2010

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

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

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

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


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

>>> s = float('nan')
>>> s == s
False
3 голосов
/ 05 июля 2010

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

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

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

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

x = bad()
print x is x, x==x # True, False
2 голосов
/ 05 июля 2010

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

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

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

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

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

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

1 голос
/ 05 июля 2010

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

0 голосов
/ 05 июля 2010

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

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

...