[Python-ideas] Give ipaddresses an __index__ method

Chris Angelico rosuav at gmail.com
Wed Feb 14 23:43:59 EST 2018


On Thu, Feb 15, 2018 at 3:14 PM, Steven D'Aprano <steve at pearwood.info> 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.

ChrisA


More information about the Python-ideas mailing list