测试 IPv4 地址是否有效

Testing to see if IPv4 address is valid

我想 return 一个布尔值,这取决于给定的地址是否是正确的 IPv4 地址。 python 中内置的 all() 有问题。我已经查看了它的文档,它看起来很简单。话虽如此,我无法让它为我的表达工作。如果您能通俗易懂地解释它是如何工作的,以及我如何更正我的代码,那就太好了。

def IPv4_address(address):

    lst_split_address = address.split(".")
    slice_split_address = [int(num) for num in lst_split_address[1:]]

    if address.count(".") != 3:
        return False
    elif address == "":
        return False
    else:
        if all(slice_split_address) >= slice_split_address[0]:
            return True
        else:
            return False


print IPv4_address("10.20.30.40")

不要重新发明轮子(除非你乐于维护轮子)。您可以使用正则表达式来验证 ipv4 地址。下面的模式是 taken from Django:

r'(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)(?:\.(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}'

如果您已经在 Django 项目的上下文中工作,您可能更愿意只导入他们的验证器并直接使用它:

from django.core.validators import validate_ipv4_address

如果您正在使用 Python3,可以使用内置的 ipaddress 模块。

至于你的代码有什么问题,我不相信 all() 函数会按照你认为的那样工作。 all() 期望布尔值的迭代,并且 returns True 如果每个布尔值都是 True.

为了让它按照您的预期工作,您可能需要像

这样的东西
all(addr_piece >= slice_split_address[0] for addr_piece in slice_split_address)

all 的文档所述,它检查列表中的每个元素是否计算为 True(基本上 bool(e)True)或者它是否为空.

现在你在 slice_split_address 中有一个整数列表,所以它会检查该列表的每个元素是否计算为 True 如果你只是像你一样调用它并且任何数字不是0 将评估为 True,但像 127.0.0.1 这样的 IP 实际上是有效的。

所以你需要的实际上是一个包含True的列表,如果对应的数字在0到255之间(含):

is_valid = [0 <= e <= 255 for e in slice_split_address]

如果你调用 all(is_valid) 它 return 如果 slice_split_address 中的每一项都在 0 到 255 之间。通常它会被组合成类似 all(0 <= e <= 255 for e in slice_split_address) 的东西.

现在您的实施中仍然存在一个问题,因为 slice_split_address 实际上不包含 IP 地址的第一个数字,因此您可以包含它。或者您真的希望第一个数字小于或等于其他三个数字?

此外,您的支票 all(…) >= … 没有意义,因为 all() 仅 returns TrueFalse 因此将其与整数进行比较不会真的没有道理。

请注意,all(is_valid) 也会 return True 到像 0.0.0.0 这样的 IP 地址,因此可能需要调整我使用的范围。

正如其他人所说,有更好的方法可以做到这一点。而且您的算法实际上并没有验证 IPv4 地址。但这是您的代码的修复版本。

def IPv4_address(address):
    if address.count(".") != 3:
        return False
    elif address == "":
        return False
    else:
        lst_split_address = address.split(".")
        slice_split_address = [int(num) for num in lst_split_address[1:]]
        head = slice_split_address[0]
        return all(u >= head for u in slice_split_address)

print IPv4_address("10.20.30.40")

输出

True

我已将 lst_split_address 内容移到 else 块中,因为如果 if / elif 部分 return False,则无需执行此操作。

all(u >= head for u in slice_split_address)

使用一个简单的生成器表达式来检查 slice_split_address 中的所有项目是否 >= 头项目。