Python中的子类和内置方法

6 投票
2 回答
2180 浏览
提问于 2025-04-16 23:05

为了方便,我想要创建一个ICMP套接字,所以想要对socket进行子类化:

class ICMPSocket(socket.socket):
    def __init__(self):
        socket.socket.__init__(
            self, 
            socket.AF_INET,
            socket.SOCK_RAW,
            socket.getprotobyname("icmp"))

    def sendto(self, data, host):
        socket.socket.sendto(self, data, (host, 1))

但是,我无法重写socket.sendto这个方法:

>>> s = icmp.ICMPSocket()
>>> s.sendto
<built-in method sendto of _socket.socket object at 0x100587f00>

这是因为sendto是一个“内置方法”。根据数据模型参考,这实际上是“一个内置函数的不同表现形式,这次包含了一个作为隐式额外参数传递给C函数的对象。”

我的问题是:在子类化时,有没有办法重写内置方法?

[编辑] 第二个问题:如果没有,为什么不可以?

2 个回答

3

重新编辑:我之前的解决方案没有奏效,经过一段时间的挣扎,我可以得出结论:在Python的socket编程中,使用组合比继承要好得多。不过,如果你想知道如何用继承来实现,可以看看这段代码:

import socket


class ICMPSocket(socket.socket):
    def __init__(self):

        self._sock = socket.socket(
                        socket.AF_INET,
                        socket.SOCK_RAW,
                        socket.getprotobyname("icmp"))

        # Delete the methods overrited by the socket initializer to make
        # possible defining our own.
        for attr in socket._delegate_methods:
            try:
                delattr(self, attr)
            except AttributeError:
                pass

    def sendto(self, data, flags, addr):
        return self._sock.sendto(data, flags, (addr, 1))

icmp = ICMPSocket()

print icmp.sendto('PING', 0, '127.0.0.1')
6

我知道这不是在回答你的问题,但你可以把这个套接字放到一个实例变量里。这也是Nobody在评论中提到的建议。

class ICMPSocket():
    def __init__(self):
        self.s = socket.socket(
            socket.AF_INET,
            socket.SOCK_RAW,
            socket.getprotobyname("icmp"))
    def sendto(self, data, host):
        self.s.sendto(data, (host, 1))
    def __getattr__(self, attr):
        return getattr(self.s, attr)

撰写回答