What is the difference between super().__repr__() and repr(super())?
Asked Answered
P

3

9

In python (3.5.2), I was expecting the repr(obj) function to call the magic method __repr__() of obj's class. However calling both of them do not seem to yield the same result. Can anyone explain why ?

Sample code :

class parent:

    def __init__(self):
        self.a = "haha"

    def __repr__(self):
        return repr(self.a)

class child(parent):
    def __init__(self):
        super().__init__()
        self.b="bebe"

    def __repr__(self):
        return "("+super().__repr__()+", "+repr(super())+", "+self.b+")"

    def print1(self):
        print("super().__repr__() returns:", super().__repr__())
        print("repr(super()) returns:", repr(super()))
        print("plom(super()).__repr__() returns:", plom(super()).__repr__())
        print("repr(plom(super())) returns:", repr(plom(super())))

def plom(var):
    return var

t=child()
print(t.__repr__())
print(repr(t))
print('-----')
t.print1()
print('-----')
print(plom(t).__repr__())
print(repr(plom(t)))

result :

>>> 
 RESTART: test super.py 
('haha', <super: <class 'child'>, <child object>>, bebe)
('haha', <super: <class 'child'>, <child object>>, bebe)
-----
super().__repr__() returns: 'haha'
repr(super()) returns: <super: <class 'child'>, <child object>>
plom(super()).__repr__() returns: 'haha'
repr(plom(super())) returns: <super: <class 'child'>, <child object>>
-----
('haha', <super: <class 'child'>, <child object>>, bebe)
('haha', <super: <class 'child'>, <child object>>, bebe)
>>> 
Poky answered 24/11, 2018 at 1:37 Comment(2)
Because super returns a proxy object, not the class itself.Almucantar
How can I get the superclass from my object itself from it, then ? and why does it work with __repr__() ? In what way is repr different from __repr__ ?Poky
C
9

Calling repr(super()) directly accesses the __repr__ on the super class (technically, the tp_repr of the C PyTypeObject struct defining the super type). Most special dunder methods behave this way when called implicitly (as opposed to explicitly calling them as methods). repr(x) isn't equivalent to x.__repr__(). You can think of repr as being defined as:

def repr(obj):
    return type(obj).__repr__(obj)  # Call unbound function of class with instance as arg

while you were expecting it to be:

def repr(obj):
    return obj.__repr__()  # Call bound method of instance

This behavior is intentional; one, customizing dunder methods per-instance makes little sense, and two, prohibiting it allows for much more efficient code at the C level (it has much faster ways of doing what the illustrative methods above do).

By contrast, super().__repr__() looks up the method on the super instance, and super defines a custom tp_getattro (roughly equivalent to defining a custom __getattribute__ method), which means lookups on the instance are intercepted before they find the tp_repr/__repr__ of the class, and instead are dispatched through the custom attribute getter (which performs the superclass delegation).

Coney answered 24/11, 2018 at 2:36 Comment(0)
A
2

If you consult the docs, you'll see that super returns a proxy object which delegates method calls to the appropriate class according to method resolution order.

So repr(super()) gets you the representation of the proxy object. Whereas the method call super().__repr__() gives you the representation defined by the next class in the method resolution order.

If you want the superclass itself, try

my_object.__mro__[1]
Almucantar answered 24/11, 2018 at 2:37 Comment(0)
P
0

In super().__repr__() you're calling the repr class of the super object so you get 'haha'

In the second, you're calling repr of the super(). what does super() output? <super: <class 'child'>, <child object>> so you're effectively calling repr on some class hierarchy

Pulp answered 24/11, 2018 at 2:9 Comment(2)
This doesn't make any sense to me : Why would super() output something different between super().__repr__() and repr(super()) ?Poky
I added some cases and I don't understand why super() would make that difference when my plom(t) function doesn't. Isn't super a regular function ?Poky

© 2022 - 2024 — McMap. All rights reserved.