On Thu, Feb 15, 2018 at 3:14 PM, Steven D'Aprano email@example.com wrote:
On Thu, Feb 15, 2018 at 11:45:46AM +1100, Chris Angelico wrote:
Except that this computer's IPv4 is not 3232235539, and I never want to enter it that way. I enter it as 192.168.0.19 - as four separate integers.
That's partly convention (and a useful convention: it is less error- prone than 3232235539) and partly that because you're a sys admin who can read the individual subfields of an IP address. I'm not suggesting you ought to change your habit.
But to civilians, 192.168.0.19 is as opaque as 3232235539 or 0xC0A80013 would be.
To some people, any form of address is as opaque as any other, true. (That's part of why we have DNS.) Also true, however, is that the conventional notation has value and meaning. That's partly historical (before CIDR, all networks were sized as either class A (10.x.y.z for any x, y, z), class B (172.16.x.y), or class C (192.168.0.x)), partly self-perpetuating (we use a lot of /24 addresses in local networks, not because we HAVE to, but because a /24 lets you lock three parts of the address and have the last part vary), but also definitely practical.
We allow creating IP address objects from a single int, we don't require four separate int arguments (one for each subfield), and unless I've missed something, IP addresses are not treated as a collection of four separate integers (or more for v6). I can't even find a method to split an address into four ints. (Nor am I sure that there is good reason to want to do so.) So calling a single address "four separate integers" is not really accurate.
The most common way to create an IPv4Address object is to construct it from a string, which has the four separate integers in it. The dots delimit those integers. It's not an arbitrary string; it is most definitely a tuple of four integers, represented in its standard string notation. Simply because it's not actually the Python type Tuple[Int] doesn't mean it isn't functionally and logically a sequence of numbers.
And if ever you actually do have the four integers, you can use a one-liner anyway:
address = (192, 168, 0, 19) ipaddress.IPv4Address("%d.%d.%d.%d" % address) IPv4Address('192.168.0.19')
It is meaningless to perform string operations on IP addresses. What would it mean to call addr.replace('.', 'Z') or addr.split('2')?
But doing at least some int operations on addresses isn't meaningless:
py> a = ipaddress.ip_address('192.168.0.19') py> a + 1 IPv4Address('192.168.0.20')
How meaningful is that, when you don't have the netmask?
a = ipaddress.ip_address('192.168.0.254') a + 1 IPv4Address('192.168.0.255') a + 2 IPv4Address('192.168.1.0') a + 3 IPv4Address('192.168.1.1')
If that's a /24, one of those is a broadcast address, one is an unrelated network address, and one is an unrelated host address. "Adding 1" to an IP address is meaningless. And it definitely does NOT mean that IP addresses should have __index__, because that implies that they truly are integers, which would mean you could do something like this:
ipaddress.IPv4Address('192.168.0.19') + ipaddress.IPv4Address("10.1.1.1") Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'IPv4Address' and 'IPv4Address'
The __int__ method converts something to an integer. Nobody is disagreeing that you can convert an IP address into an integer. But they are NOT integers. It doesn't make sense to treat one as an integer implicitly.