Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why would a python class that inherits 'object' call 'super' in its __init__ method?

I was poking around at the source of the requests module, and noticed this code:

class Response(object):
    """The :class:`Response <Response>` object, which contains a
    server's response to an HTTP request.
    """

    def __init__(self):
        super(Response, self).__init__()
        ... more init method...

My understanding of super() suggests this call wouldn't do anything at all. I've found quite a few questions about superclass calling, but all work from subclasses of other classes, not object itself. The python docs, too, don't mention this construction.

It occurred to me this might simply be a mistake, and if you git blame that file to the commit that introduced that line, you'll see that at the time of authorship, Response was a subclass of BaseResponse. Is the line just a holdover from a class refactoring, or does it this super() call do anything at all?

like image 424
Christopher Avatar asked Oct 09 '13 18:10

Christopher


2 Answers

This code might actually do something if Response becomes part of a multiple inheritance tree. The next class in the "MRO" list could be something other than object! In that case, the call to super could be very much necessary.

For example,

class NewerClass(A, Response):
    def __init__(self):
        ... do stuff ...
        super(NewerClass, self).__init__()

From that class definition and without knowing what the hierarchy of A is, you can not determine what the next class that super(Response, self).__init__() calls will be. It might be object or it might be a base class of A.

I think one problem is that the name super causes confusion. It does not act like Smalltalk's super variable unless you only use single inheritance, and it does not return a "super class" object. Instead what it is doing is figuring out the "next" class to be used according to MRO order.

Classic articles on the subject are: Python's Super Considered Super and Python's Super Considered Harmful.

like image 53
darinbob Avatar answered Nov 16 '22 19:11

darinbob


As mentioned in Corley Brigman's comment, it's unnecessary but harmless.

For some background, the BaseResponse class was added during Kenneth's sprint on Requests 1.0. The 1.0 code change introduced transport adapters, which make it possible to define specific behaviour for some HTTP endpoints (or indeed non-HTTP endpoints). An important part of the Transport Adapter interface is the HTTPAdapter.build_response() method, which takes the returned raw response from HTTPAdapter.send() and builds a Requests Response object from it.

It is clear that Kenneth saw potential utility in having some form of abstract base class for Responses, which would allow transport adapters to return Responses with very different behaviours to the standard HTTP Response object. For this reason, the refactor into an ABC with the bulk of the logic in the subclass seemed to make sense.

Later in the refactor this got yanked out again as unnecessary complexity. The reality is that people wanting to define specialised Response objects can simply subclass Response, rather than having an ABC that does nothing much. This makes the mainline use case (vanilla Requests) much cleaner in the code, and takes away almost no utility.

When the BaseRequest class got pulled out, this line got overlooked, but since it causes no problems there's never been need to remove it.

like image 40
Lukasa Avatar answered Nov 16 '22 17:11

Lukasa