Cezar Spatariu Neagu
Cezar Spatariu Neagu

Reputation: 48

Python 2.7 inheritance super() method invocation

I do try in Python 2.7 to use inheritance and create a second class that that will use super method in conjunction with @classmethod decorator to initialise the base class. But I am still not able to make it work even after I add the *args and **kwargs parameters to the function that initialise the base class.

import socket


class Server(object):

    def __init__(self, ip_address, host):
        self.ip_address = ip_address
        self.host = host

    @classmethod
    def create_with_host(cls, host, *args, **kwargs):
        ip_address = socket.gethostbyname(host)
        return cls(ip_address, host, *args, **kwargs)


class WebServer(Server):

    def __init__(self, url):
        super(WebServer, self).create_with_host(url.split('/')[2])
        self.url = url


if __name__ == '__main__':
    s1 = Server.create_with_host('www.google.com')
    print(s1.host, s1.ip_address)
    w1 = WebServer('http://app.pluralsight.com')
    print(w1.host, w1.ip_address, w1.url)

The error is:

Traceback (most recent call last):
  File "/Users/poc.py", line 26, in <module>
    w1 = WebServer('http://app.pluralsight.com')
  File "/Users/poc.py", line 19, in __init__
    super(WebServer, self).create_with_host(url.split('/')[2])
  File "/Users/poc.py", line 13, in create_with_host
    return cls(ip_address, host, *args, **kwargs)
TypeError: __init__() takes exactly 2 arguments (3 given)

Upvotes: 0

Views: 315

Answers (1)

jonrsharpe
jonrsharpe

Reputation: 122024

You have several problems here, but first among them are:

  1. You are calling __init__ with arbitrary positional and keyword arguments, but neither accepts those - they need to be in the signature, not just the call. In this case, you don't really need them anyway; and
  2. Your subclassing has broken the signature of the class - WebServer takes different initialisation arguments than Server, so you can't use one where the other is expected. As in Server, you should use a @classmethod for alternative initialisation options.

Here's a working implementation:

import socket


class Server(object):

    def __init__(self, ip_address, host):
        self.ip_address = ip_address
        self.host = host

    @classmethod
    def create_with_host(cls, host):
        ip_address = socket.gethostbyname(host)
        return cls(ip_address, host)


class WebServer(Server):

    @classmethod
    def create_with_url(cls, url):
        inst = cls.create_with_host(url.split('/')[2])
        inst.url = url
        return inst

Note that super isn't required here, as WebServer doesn't override any of the methods it inherits.

Upvotes: 3

Related Questions