问题
If someone writes a class in python, and fails to specify their own __repr__()
method, then a default one is provided for them. However, suppose we want to write a function which has the same, or similar, behavior to the default __repr__()
. However, we want this function to have the behavior of the default __repr__()
method even if the actual __repr__()
for the class was overloaded. That is, suppose we want to write a function which has the same behavior as a default __repr__()
regardless of whether someone overloaded the __repr__()
method or not. How might we do it?
class DemoClass:
def __init__(self):
self.var = 4
def __repr__(self):
return str(self.var)
def true_repr(x):
# [magic happens here]
s = "I'm not implemented yet"
return s
obj = DemoClass()
print(obj.__repr__())
print(true_repr(obj))
Desired Output:
print(obj.__repr__())
prints 4
, but print(true_repr(obj))
prints something like:<__main__.DemoClass object at 0x0000000009F26588>
回答1:
You can use object.__repr__(obj)
. This works because the default repr
behavior is defined in object.__repr__
.
回答2:
Note, the best answer is probably just to use object.__repr__
directly, as the others have pointed out. But one could implement that same functionality roughly as:
>>> def true_repr(x):
... type_ = type(x)
... module = type_.__module__
... qualname = type_.__qualname__
... return f"<{module}.{qualname} object at {hex(id(x))}>"
...
So....
>>> A()
hahahahaha
>>> true_repr(A())
'<__main__.A object at 0x106549208>'
>>>
回答3:
Typically we can use object.__repr__
for that, but this will to the "object repr for every item, so:
>>> object.__repr__(4)
'<int object at 0xa6dd20>'
Since an int
is an object
, but with the __repr__
overriden.
If you want to go up one level of overwriting, we can use super(..)
:
>>> super(type(4), 4).__repr__() # going up one level
'<int object at 0xa6dd20>'
For an int
that thus again means that we will print <int object at ...>
, but if we would for instance subclass the int
, then it would use the __repr__
of int
again, like:
class special_int(int):
def __repr__(self):
return 'Special int'
Then it will look like:
>>> s = special_int(4)
>>> super(type(s), s).__repr__()
'4'
What we here do is creating a proxy object with super(..)
. Super will walk the method resolution order (MRO) of the object and will try to find the first function (from a superclass of s
) that has overriden the function. If we use single inheritance, that is the closest parent that overrides the function, but if it there is some multiple inheritance involved, then this is more tricky. We thus select the __repr__
of that parent, and call that function.
This is also a rather weird application of super
since usually the class (here type(s)
) is a fixed one, and does not depend on the type of s
itself, since otherwise multiple such super(..)
calls would result in an infinite loop.
But usually it is a bad idea to break overriding anyway. The reason a programmer overrides a function is to change the behavior. Not respecting this can of course sometimes result into some useful functions, but frequently it will result in the fact that the code contracts are no longer satisfied. For example if a programmer overrides __eq__
, he/she will also override __hash__
, if you use the hash of another class, and the real __eq__
, then things will start breaking.
Calling magic function directly is also frequently seen as an antipattern, so you better avoid that as well.
来源:https://stackoverflow.com/questions/48777014/how-can-we-get-the-default-behavior-of-repr