I'm working with a 3rd-party library which has a poor repr for a class and I would like to overwrite it once an instance of that class has been created.
I saw how to create bound methods in an existing object.
class toy():
pass
inst= toy()
class inhtoy():
def __new__(cls,obj):
def __repr__(self):
return 'Sucessful'
import types
obj.__repr__ = types.MethodType(__repr__,obj)
return obj
t = inhtoy(inst)
Indeed, if I call t.repr() it works, however it does not overwrite the original repr. It appears as <bound method inhtoy.__new__.<locals>.__repr__ of <__main__.toy object at 0x7f76e0b61f98>>
a kind of local method.
Calling repr(t)
still points to the original representation '<__main__.toy object at 0x7f76e0b61f98>'
but not the overwritten one.
Is there a way to properly do this?
Thanks
@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)
after some looking around i found this answer. the way to do it is on a live instance is:
t.__class__.__repr__ = my_custom_repr
please note that this changes all class instances and not just this instance
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With