class T():
...
t = T()
t.__str__ = types.MethodType(lambda self: "qqqqqq", t)
print(t) # default object.__repr__
Сould you explain to me the reason for this behavior. Maybe there is some solution?
>Solution :
str(t) calls t.__class__.__str__(t), not t.__str__():
class T:
pass
t = T()
t.__str__ = lambda: "foo"
print(t) # <__main__.T object at 0x000001FA84DA7D60>
print(t.__str__()) # foo
T.__str__ = lambda self: "foo"
print(t) # foo
This is because special methods have special rules for how they’re looked up:
https://docs.python.org/3/reference/datamodel.html#special-method-lookup
For custom classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary
In general, the solution is to define __str__ in your actual class, and have its implementation be informed by class attributes as needed, rather than monkey-patching the entire method in individual instances:
class T:
def __str__(self):
return "foo"
t = T()
print(t) # foo