我知道如何将 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
模块,我坚持这个选择。我想学习,并将其视为挑战。