Python обычно вызывает специальные методы (те, имя которых окружено __) не в экземпляре, а только в классе. (Хотя это деталь реализации, она характерна для CPython, стандартного интерпретатора.) Таким образом, нет способа переопределить __repr__() непосредственно в экземпляре и заставить его работать. Вместо этого вам нужно сделать что-то вроде этого:
Для пользовательских классов неявные вызовы специальных методов гарантированно работают корректно, только если они определены в типе объекта, а не в словаре экземпляра объекта … В дополнение к обходу любых атрибутов экземпляра в интересах корректности, неявный поиск специальным методом обычно также обходит __getattribute__() метод даже метакласса объекта
(Часть, которую я вырезал, объясняет обоснование этого, если вам это интересно.)
Python не документирует точно, когда реализация должна или не должна искать метод в типе; все, что он документирует, это, по сути, то, что реализации могут или не могут просматривать экземпляр для поиска специальных методов, поэтому вам не следует рассчитывать ни на то, ни на другое.
Как вы можете догадаться по результатам вашего тестирования, в реализации CPython, __repr__ это одна из функций, которые просматриваются по типу.
В 2.x все немного по-другому, в основном из-за наличия классических классов, но пока вы создаете только классы нового стиля, вы можете думать о них как об одном и том же.
Наиболее распространенная причина, по которой люди хотят это сделать, - это обезличивать разные экземпляры объекта для выполнения разных действий. Вы не можете сделать это специальными методами, так что ... что вы можете сделать? Есть чистое решение и хакерское решение.
Чистым решением является реализация специального метода в классе, который просто вызывает обычный метод в экземпляре. Затем вы можете обезьяньим способом исправить этот обычный метод в каждом экземпляре. Например:
Простое решение заключается в создании нового подкласса "на лету" и переклассификации объекта. Я подозреваю, что любой, у кого действительно есть ситуация, когда это хорошая идея, поймет, как ее реализовать, из этого предложения, а любой, кто не знает, как это сделать, не должен пытаться, поэтому я оставлю все как есть.
Ответ 3
Причина этого в том, что специальные методы (__x__()) определены для класса, а не для экземпляра.
Это имеет смысл, если подумать о __new__() - было бы невозможно вызвать это в экземпляре, поскольку экземпляр не существует на момент его вызова.
Таким образом, вы можете сделать это для класса в целом, если хотите:
>>> A.__repr__ = __repr__ >>> a A
Или в отдельном экземпляре, как в ответе киндалла. (Обратите внимание, что здесь много сходства, но я подумал, что мои примеры добавили достаточно, чтобы опубликовать и это).
Ответ 4
Для классов нового стиля Python использует специальный метод lookup, который обходит экземпляры. Вот выдержка из источника:
1164 /* Internal routines to do a method lookup in the type 1165 without looking in the instance dictionary 1166 (so we can't use PyObject_GetAttr) but still binding 1167 it to the instance. The arguments are the object, 1168 the method name as a C string, and the address of a 1169 static variable used to cache the interned Python string. 1170 1171 Two variants: 1172 1173 - lookup_maybe() returns NULL without raising an exception 1174 when the _PyType_Lookup() call fails; 1175 1176 - lookup_method() always raises an exception upon errors. 1177 1178 - _PyObject_LookupSpecial() exported for the benefit of other places. 1179 */
Вы можете либо перейти на класс старого стиля (не наследуется от object), либо добавить в класс методы диспетчера (методы, которые перенаправляют запросы обратно в экземпляр). Пример методов диспетчера экземпляра приведен по ссылке http://code.activestate.com/recipes/578091