ip_network возвращает не строку и не число, а объект сети – экземпляр класса IPv4Network. Он описывает сразу весь диапазон адресов: от адреса сети до широковещательного. Думать о нём удобнее всего как о списке адресов, у которого есть ещё и свойства всей сети целиком.
Свойства сети пишутся без скобок: это не методы, а уже посчитанные значения.
| Запись |
Что это |
Для 192.168.156.0/22 |
net.network_address |
адрес сети: все биты узла – нули |
192.168.156.0 |
net.broadcast_address |
широковещательный адрес: все биты узла – единицы |
192.168.159.255 |
net.netmask |
маска |
255.255.252.0 |
net.hostmask |
обратная маска: единицы там, где у маски нули |
0.0.3.255 |
net.prefixlen |
длина маски – сколько в ней единиц |
22 |
net.num_addresses |
сколько адресов в сети, служебные тоже |
1024 |
net.with_prefixlen |
сеть строкой, маска числом после косой черты |
192.168.156.0/22 |
Сеть ведёт себя как список адресов: у неё есть индексы, в том числе отрицательные, её можно перебрать циклом for и проверить оператором in, входит ли в неё адрес. Адрес для такой проверки создаёт ip_address из того же модуля.
| Запись |
Что это |
Для 192.168.156.0/22 |
net[0] |
адрес сети |
192.168.156.0 |
net[1] |
первый адрес, который можно выдать компьютеру |
192.168.156.1 |
net[-2] |
последний адрес, который можно выдать компьютеру |
192.168.159.254 |
net[-1] |
широковещательный адрес |
192.168.159.255 |
len(list(net.hosts())) |
hosts() – метод, со скобками: адреса без адреса сети и широковещательного |
1022 |
ip_address('192.168.159.86') in net |
входит ли адрес в сеть |
True |
ip_address('192.168.160.1') in net |
соседний адрес за границей сети |
False |
Каждый адрес – тоже объект, IPv4Address. Печатается он привычной записью с точками, а внутри это 32-битное число, и с ним можно обращаться как с числом:
from ipaddress import ip_address
addr = ip_address('192.168.159.86')
print(addr) # 192.168.159.86
print(int(addr)) # 3232276310
print(bin(int(addr))) # 0b11000000101010001001111101010110
print(addr + 1) # 192.168.159.87
print(str(addr).split('.')) # ['192', '168', '159', '86']
Из этих трёх превращений и собираются ответы задания: int(ip) делает из адреса число, bin(int(ip)) – строку битов, в которой можно считать единицы, а str(ip) – запись с точками, из которой получают сумму октетов или адрес без разделителей.