Инициализация подкласса с существующим экземпляром суперкласса в python3 - PullRequest
1 голос
/ 27 мая 2019

Я пишу свою собственную версию класса сокетов в Python.Мне было интересно, есть ли способ не инициализировать подкласс, используя его метод __init__, а скорее инициализировать его, используя существующий экземпляр класса сокетов .

В основном то, что я пытаюсь сделать, это наследовать от класса сокета и переписать метод 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 ]

1 голос
/ 27 мая 2019

Итак, вы хотите что-то похожее на конструктор копирования .

Хотя есть некоторые вещи, которые указывают на XY Проблема , есть простая альтернатива (если я все понял правильно).

Согласно [Python 3.Docs]: сокет. сокет ( family = AF_INET, тип = SOCK_STREAM, proto = 0, fileno = Нет) :

Если указано fileno , значения для family , type и proto автоматически определяются из указанного файлового дескриптора .

Кажется, это именно то, что вам нужно.

Примечание : учтите, что accept возвращает кортеж , а переопределение - нет, поэтому ваш класс API несовместим с его предком.

Вот фрагмент кода, который должен делать то, что вы хотите:

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
1 голос
/ 27 мая 2019

Вот исходный код для 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() правильный, поэтому мы можем создать метод класса, который повторяет его функциональность:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...