@Nullman's answer works, because their solution is actually changing the class object toy
, that t
is an instance of, not the instance itself, as your approach does.
The special attribute __class__
references the class object an instance belongs to.
print(t.__class__ is toy) # True
So, t.__class__.__repr__ = my_custom_repr
assigns to __repr__
on the class toy
, not on the instance t
.
This becomes visible when comparing the output of print(t.__repr__)
between your approach and Nullman's. Assuming that a module-level function __repr__
looks like this:
def __repr__(self):
return repr(self.__class__)
Your solution shows:
<bound method __repr__ of <__main__.toy object at 0x00000000029E5A90>>
Note, it says __main__.toy object
.
Nullman's solution shows it as:
<bound method __repr__ of <class '__main__.toy'>>
When you invoke t.__repr__()
using your approach, you call the method you set on the instance t
, hence it returns what you made it retun; the string Success
in your example.
When using repr()
, however, the class defines the output:
A class can control what this function returns for its instances by
defining a __repr__()
method.
As Nullman rightfully pointed out, their approach will change the behavior of all existing and future objects, instantiated from toy
.
As for the strange name, that the assigned method shows when using your code:
<bound method inhtoy.__new__.<locals>.__repr__ of <__main__.toy object at 0x7f76e0b61f98>>
... that's the function object's qualified name coming from the __qualname__
special attribute. It's the function __repr__
from the local scope of your class inhtoy
's method __new__
.
Speaking of which, passing your instance inst
through the magic method __new__
of your inhtoy
class does not really achieve much. Your code is functionally equivalent to:
def __repr__(self):
return "Success"
inst.__repr__ = types.MethodType(__repr__, obj)