Это странная вещь, которую нужно делать, и обычно функция или метод должны делать то же самое, кто бы ни вызывал ее. Но в этом случае __repr__
предназначен только для удобства программиста, поэтому удобство кажется достаточно веской причиной, чтобы заставить его работать так, как вы просите.
Однако, к сожалению, то, что вы хотите, не так ' На самом деле это возможно, потому что по какой-либо причине метод list.__repr__
не отображается в стеке. Я тестировал в Python 3.5.2 и Python 3.8.1:
>>> class ReprRaises:
... def __repr__(self):
... raise Exception()
...
>>> r = ReprRaises()
>>> r
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __repr__
Exception
>>> [r]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __repr__
Exception
Как видите, стек одинаков независимо от того, находится ли объект repr
'd в список. (Кадр __repr__
в стеке принадлежит классу ReprRaises
, а не list
.)
Я также тестировал с использованием inspect.stack
:
>>> import inspect
>>> class ReprPrints:
... def __repr__(self):
... print(*inspect.stack(), sep='\n')
... return 'foo'
>>> r = ReprPrints()
>>> r
FrameInfo(frame=<frame object at 0x7fcbe4a38588>, filename='<stdin>', lineno=3, function='__repr__', code_context=None, index=None)
FrameInfo(frame=<frame object at 0x7fcbe44fb388>, filename='<stdin>', lineno=1, function='<module>', code_context=None, index=None)
foo
>>> [r]
FrameInfo(frame=<frame object at 0x7fcbe4a38588>, filename='<stdin>', lineno=3, function='__repr__', code_context=None, index=None)
FrameInfo(frame=<frame object at 0x7fcbe44fb388>, filename='<stdin>', lineno=1, function='<module>', code_context=None, index=None)
[foo]
Опять же, в стеке вызовов нет видимой разницы между самим объектом и объектом в списке; поэтому вам не нужно проверять __repr__
.
Итак, самое близкое, что вы можете получить - это какая-то функция print_like_I_want
. Это можно, по крайней мере, записать так, чтобы каждый класс мог определить свое собственное поведение:
def pp(obj):
try:
_pp = obj._pp
except AttributeError:
print(repr(obj))
else:
print(_pp())
Единственный способ, которым я могу придумать, сделать это с меньшим количеством нажатий клавиш, это перегрузить унарный оператор, как обычно бесполезный унарный плюс :
>>> class OverloadUnaryPlus:
... def __repr__(self):
... return 'foo'
... def __pos__(self):
... print('bar')
...
>>> obj = OverloadUnaryPlus()
>>> obj
foo
>>> +obj
bar