Есть ли какая-либо причина x == x не оценивается быстро? Я надеялся, что __eq__ будет проверять, совпадают ли его два аргумента, и если так немедленно вернуть True. Но он этого не делает:
s = set(range(100000000))
s == s # this doesn't short-circuit, so takes ~1 sec
Для встроенных модулей x == x всегда возвращает True, я думаю? Для пользовательских классов, я думаю, кто-то может определить __eq__, который не удовлетворяет этому свойству, но есть ли разумный прецедент для этого?
Причина, по которой я хочу, чтобы x == x была быстро оценена, - это то, что она имеет огромную производительность при memoizing функциями с очень большими аргументами:
from functools import lru_cache
@lru_cache()
def f(s):
return sum(s)
large_obj = frozenset(range(50000000))
f(large_obj) # this takes >1 sec every time
Обратите внимание, что причина @lru_cache неоднократно медленна для больших объектов не потому, что ей нужно вычислить __hash__ (это делается только один раз и затем жестко кэшируется, поскольку указал by @jsbueno), но из-за того, что таблица хеш-словаря должна выполняться __eq__ каждый раз, чтобы убедиться, что он нашел нужный объект в ведре (очевидно, недостаточно равенства хэшей).
UPDATE:
Кажется, стоит рассмотреть этот вопрос отдельно для трех ситуаций.
1) Пользовательские типы (т.е. не встроенная/стандартная библиотека).
Как отметил @donkopotamus, бывают случаи, когда x == x не следует оценивать True. Например, для типов numpy.array и pandas.Series результат намеренно не конвертируется в логическое, потому что он неясно, какова должна быть естественная семантика (означает ли False, что контейнер пуст, или это означает, что все элементы в нем False?).
Но здесь нет необходимости в том, чтобы python что-либо делал, поскольку пользователи всегда могут коротко закоротить x == x сравнение, если это необходимо:
def __eq__(self, other):
if self is other:
return True
# continue normal evaluation
2) Типы встроенных/стандартных библиотек Python.
a) Неконтейнеры.
Насколько мне известно, короткое замыкание может быть уже реализовано для этого случая - я не могу сказать, так как в любом случае это очень быстро.
b) Контейнеры (включая str).
Как комментирует @Karl Knechtel, добавление короткого замыкания может повредить общую производительность, если экономия от короткого замыкания перевешивается дополнительными накладными расходами в случаях, когда self is not other. Хотя теоретически возможно, даже в этом случае накладные расходы являются небольшими в относительных терминах (сравнение контейнеров никогда не бывает супербыстро). И, конечно же, в случаях, когда короткое замыкание помогает, экономия может быть значительно.
Кстати, оказывается, что str делает короткое замыкание: мгновенное сравнение огромных одинаковых строк.