Python 2.7 继承super()方法调用

Python 2.7 inheritance super() method invocation

我确实在 Python 2.7 中尝试使用继承并创建第二个 class,它将使用 super 方法结合 @classmethod 装饰器来初始化基础class。但是即使我将 *args**kwargs 参数添加到初始化基础 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)

错误是:

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)

这里有几个问题,但首先是:

  1. 您正在使用任意位置和关键字参数调用 __init__,但 都不接受那些 - 它们需要在签名中,而不仅仅是调用中。在这种情况下,您实际上并不需要它们;和
  2. 你的 subclassing 破坏了 class 的签名 - WebServer 采用与 Server 不同的初始化参数,所以你不能使用其他预计。与 Server 一样,您应该使用 @classmethod 作为替代初始化选项。

这是一个有效的实现:

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

请注意,此处不需要 super,因为 WebServer 不会覆盖它继承的任何方法。