如何将 int 子类化为 IP 地址数据类?

问题描述 投票:0回答:0

我知道如何将 IPv4 和 IPv6 地址转换为

int
(不使用
ipaddress
模块),反之亦然。我已经编写了相关的工作代码。这篇文章不是关于那个的。

我创建了一个表示 IPv4 和 IPv6 地址的类,它有一堆属性,即

integer
string
hexadecimal
version
maxpower
pointer
maxpower
表示一个版本的IP地址总数以2为底的对数,其他的都很好理解。

我想让它成为一个冻结的数据类,并添加类似

tuple
dict
的方法,我已经知道该怎么做,但我也想使它成为
int
的子类,我不知道如何让他们一起工作。

为什么我要让它成为

int
的子类?因为 IP 地址与整数是一一对应的,而且它们实际上只是整数。我想让他们有适当的比较方法,如
int
s 和
int
.

的其他方法

这里是类定义:

class IP_Address:
    def __str__(self) -> str:
        return self.string

    def __int__(self) -> int:
        return self.integer

    def __repr__(self) -> str:
        return f"IP_Address(string='{self.string}', integer={self.integer}, version={self.version.__name__})"

    def __hash__(self) -> int:
        return hash(self.integer)
    
    def __eq__(self, other) -> bool:
        assert isinstance(other, (int, IP_Address))
        return hash(self) == hash(other)
    
    def __ne__(self, other) -> bool:
        return not self == other
    
    def __ge__(self, other) -> bool:
        assert isinstance(other, (int, IP_Address))
        value = other if isinstance(other, int) else other.integer
        return self.integer >= value
    
    def __lt__(self, other) -> bool:
        return not self >= other
    
    def __gt__(self, other) -> bool:
        return self >= other and self != other
    
    def __le__(self, other) -> bool:
        return self < other or self == other
    
    def __init__(self, value: int | str, version: IPv4 | IPv6 = None) -> None:
        if isinstance(value, str):
            self.from_string(value, version)
        else:
            self.from_integer(value, version)

        self.maxpower = 32 if self.version == IPv4 else 128
        self.hexadecimal = f'{self.integer:08x}' if version == IPv4 else f'{self.integer:032x}'
        self.pointer = None

    def from_string(self, value: str, version: IPv4 | IPv6) -> None:
        if not version:
            version = IPv4 if IPV4_PATTERN.match(value) else IPv6
        self.integer = version.parser(value)
        self.string = value
        self.version = version

    def from_integer(self, value: int, version: IPv4 | IPv6) -> None:
        assert isinstance(value, int)
        if not version:
            version = IPv4 if 0 <= value <= MAX_IPV4 else IPv6
        self.string = version.formatter(value)
        self.integer = value
        self.version = version

    def get_pointer(self) -> str:
        if not self.pointer:
            if self.version == IPv4:
                self.pointer = '.'.join(
                    self.string.split('.')[::-1]
                ) + '.in-addr.arpa'
            else:
                self.pointer = '.'.join(self.hexadecimal[::-1])+'.ip6.arpa'
        return self.pointer

所以我打算让它们在整数域中进行操作,但是覆盖

__str__
方法以返回IPv4的点分base-256十进制表示法,以及IPv6的冒号分隔的base-65536十六进制表示法,覆盖
__repr__
到赋予数据类风格表示,并为其添加反向指针属性和IP版本属性。

我已经写了所有的代码,但是我没有弄清楚如何在做所有这些的同时也使它成为

int
的子类。我尝试实现了所有 dunder 方法,但很快就明白这应该是
int
的子类,但我不知道该怎么做。我需要设置所有这些属性,并且该类必须能够从整数表示和字符串表示中实例化。最重要的是,我还打算使它成为一个数据类,并使用包装器来添加
dict
-like和
tuple
-like方法。

我如何正确地使用我目前拥有的类,将它变成

int
的子类,同时确保它也适用于包装器?


无论好坏,我特别选择不使用

ipaddress
模块,我坚持这个选择。我想学习,并将其视为挑战。

python python-3.x subclass
© www.soinside.com 2019 - 2024. All rights reserved.