Почему / Когда в Python `x == y` вызывает` y .__ eq __ (x) `?

37
задан Singletoned 18 February 2010 в 10:03
поделиться

4 ответа

Вам не хватает ключевого исключения из обычного поведения: когда правый операнд является экземпляром подкласса класса левого операнд, специальный метод для правого операнда вызывается первым.

См. Документацию по адресу:

http://docs.python.org/reference/datamodel.html#coercion-rules

и, в частности, следующие два абзаца:

Для объектов x и y , сначала выполняется попытка x .__ op __ (y) . Если это не реализовано или возвращает NotImplemented , y .__ rop __ (x) пробуется. Если это также не реализовано или возвращает NotImplemented , возникает исключение TypeError. Но см. следующее исключение:

Исключение из предыдущего элемента: если левый операнд является экземпляром встроенного типа или класса нового стиля, , а правый операнд является экземпляром надлежащего подкласса этого типа или класса и переопределяет базовый метод __ rop __ () , метод правого операнда __ rop __ () пробуется перед методом левого операнда __ op __ () .

31
ответ дан 27 November 2019 в 04:59
поделиться

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

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

-121--3559932-

Фактически в документах указано:

[ __ cmp __ вызывается операциями сравнения, если не определено богатое сравнение (см. выше).

__ eq __ богатый метод сравнения и, в случае TestCmp, не определен, следовательно запрос __ cmp __

6
ответ дан 27 November 2019 в 04:59
поделиться

Этот код выдаст ArithmeticException :

int x = 1 / 0;
-121--2843426-

Я думаю, что вы совершенно правы. От. Руководство по проектированию Net Framework , написанное некоторыми ведущими архитекторами Microsoft:

НЕ . Исключения должны часто разрешается распространять вверх стек вызовов.

В хорошо написанном коде попробуйте окончательно [или использование] встречается гораздо чаще, чем выгода попытки. Это может показаться сначала контринтуитив, но поймать блоки не нужны в удивительном количество дел. С другой стороны, вы всегда должны учитывать, try-finally [или использование] может быть полезным для очистки.

стр. 230 раздел 7,2

-121--3428877-

Как я знаю, _ _ eq _ _ () является так называемым методом "богатого сравнения" и вызывается для операторов сравнения в предпочтении _ _ cmp _ _ () ниже. _ _ cmp _ _ () вызывается, если не определено "богатое сравнение".

Так в A = = B:
Если в A определено _ _ eq _ _ () , то оно будет называться
Иначе _ _ cmp _ _ () будет вызываться

_ _ eq _ _ () , определенный в "str", так что ваша функция _ _ cmp _ _ () не была вызвана.

То же правило применяется для методов _ _ ne _ _ (), __gt__ (), __ge__ (), __lt__ () и _ _ le _ _ () "богатого сравнения".

1
ответ дан 27 November 2019 в 04:59
поделиться

Разве это не документировано в Language Reference? Просто из беглого просмотра, похоже, что __cmp__ игнорируется, когда определены __eq__, __lt__ и т.д. Я так понимаю, что это включает случай, когда __eq__ определен в родительском классе. str.__eq__ уже определен, поэтому __cmp__ на его подклассах будет проигнорирован. object.__eq__ и т.д. не определены, поэтому __cmp__ для его подклассов будет игнорироваться.

В ответ на уточняющий вопрос:

Я знаю, что __eq__ вызывается в... предпочтительнее, чем __cmp__, но мне не ясно почему y.__eq__(x) вызывается предпочтительнее, чем . предпочтение x.__eq__(y), в то время как последнее - это то, что, согласно документации произойдет.

В документации сказано, что сначала будет вызван x.__eq__(y), но у него есть возможность вернуть NotImplemented, в этом случае будет вызван y.__eq__(x). Я не совсем понимаю, почему вы уверены, что здесь происходит что-то другое.

Какой именно случай вызывает у вас недоумение? Я так понимаю, что вы озадачены только случаями "b" == tsc и tsc == "b", верно? В любом случае вызывается str.__eq__(onething, otherthing). Поскольку вы не переопределили метод __eq__ в TestStrCmp, в конечном итоге вы просто полагаетесь на базовый метод string, и он говорит, что объекты не равны.

Не зная деталей реализации str.__eq__, я не знаю, вернет ли ("b").__eq__(tsc) NotImplemented и даст ли tsc шанс обработать тест на равенство. Но даже если это произойдет, то, как вы определили TestStrCmp, вы все равно получите ложный результат.

Поэтому неясно, что неожиданного вы здесь видите.

Возможно, происходит то, что Python предпочитает __eq__, а не __cmp__, если он определен для любого из сравниваемых объектов, тогда как вы ожидали, что __cmp__ на самом левом объекте будет иметь приоритет над __eq__ на правом объекте. Так?

1
ответ дан 27 November 2019 в 04:59
поделиться
Другие вопросы по тегам:

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