使用python3中的现有超类实例初始化子类

时间:2019-05-27 10:25:34

标签: python python-3.x sockets inheritance superclass

我正在用python编写自己的套接字类版本。 我想知道是否有一种方法可以使用其__init__方法来初始化子类,而是使用套接字类的现有实例来对其进行初始化。 / p>

基本上,我想做的是从套接字类继承,并覆盖accept()方法以返回我自己的类而不是套接字类的对象。

要解决此问题,我想实现在自定义套接字类的__init__方法中设置基本套接字的可能性,该方法将套接字的实例作为参数并创建一个新的实例我的自定义套接字类使用套接字类的现有实例,或使用fromSocket()类方法进行相同的操作。

我现在的问题是如何在不使用属性包含套接字对象的情况下,将我自己的套接字的套接字类的现有实例设置为超类? (甚至可以在python中使用吗?)

我发现的所有其他相关问题都更多关于如何在运行时更改超类。我可能在某处忽略了答案,但找不到。

我的代码如下:

import socket
class MySocket(socket.socket):
    def __init__(self, sock:socket.socket=None):
        if sock != None:
            # initialize using existing instance contained in sock
            # How? (My question)
        else:
            super().__init__() # Default conf is enough for now
    def accept(self):
        s, addr = super().accept()
        return MySocket(sock=s) # <= This is what I want to do

我想这样称呼它:

s = MySocket()
# Call bind and listen, left out because it doesn't matter here
client, addr = s.accept() 
# Client is an instance of socket.socket, but it should be MySocket

2 个答案:

答案 0 :(得分:1)

这是socket.accept()的源代码。

老实说,这似乎是socket类的一个错误,他们已经对其进行硬编码以创建socket的新实例:

sock = socket(self.family, self.type, self.proto, fileno=fd)

当它应该获取self的类型时:

sock = type(self)(self.family, self.type, self.proto, fileno=fd)

这似乎是通过多种方法完成的,看来您最好的机会是将所有属性手动从返回的套接字复制到您的自定义实例。 dup() method希望是正确的,因此我们可以创建一个重复其功能的类方法:

import socket

class MySocket(socket.socket):
    @classmethod
    def from_socket(cls, sock):
        fd = socket.dup(sock.fileno())
        my_sock = cls(sock.family, sock.type, sock.proto, fileno=fd)
        my_sock.settimeout(sock.gettimeout())
        return my_sock

答案 1 :(得分:1)

所以您想要类似 copy构造函数的东西。

尽管有些东西表明 XY问题,但是有一个简单的选择(如果我没事的话)。

根据[Python 3.Docs]: socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)

  

如果指定了 fileno ,则会从以下位置自动检测家族 type proto 的值指定的文件描述符。

这似乎完全可以满足您的需求。

注意:请记住, 接受会返回一个元组,而您的覆盖不会返回,因此您的类 API < / em>与祖先不兼容。

这是一段应该执行您想要的代码:

class CustomSocket(socket.socket):
    def accept(self):
        conn, addr = super().accept()
        custom_conn = CustomSocket(conn.family, conn.type, conn.proto, conn.fileno())
        return custom_conn, addr