2016-10-26 2 views
0

Я хочу вернуть логическое значение в зависимости от того, является ли указанным адресом правильный IPv4-адрес или нет. У меня возникла проблема со всем(), встроенным в python. Я просмотрел документацию на нем, и это кажется прямым. Говоря это, я не могу заставить его работать для моего выражения. Если бы вы могли объяснить, как это работает, и как я могу исправить свой код, это было бы здорово.Проверка правильности адреса IPv4

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") 

ответ

1

Как сказано в документации all, он проверяет, является ли каждый элемент списка вычисляется в True (в основном bool(e) является True) или он пуст.

Теперь у вас есть список целых чисел в slice_split_address и поэтому он будет проверять, если каждый элемент этого списка имеет значение True, если вы просто назвать его, как вы делаете, и любое число, отличное от 0 будет вычисляться True, но IP как 127.0.0.1 действительно действительный.

Так что вам нужно на самом деле список, который содержит True, если соответствующее число в диапазоне от 0 до 255 (включительно):

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

Если вы звоните, то all(is_valid) он возвращается, если каждый элемент в slice_split_address между 0 и 255. Обычно он будет объединен в нечто вроде all(0 <= e <= 255 for e in slice_split_address).

В вашей реализации все еще есть одна проблема, потому что slice_split_address фактически не содержит первый номер IP-адреса, поэтому вы можете включить его. Или вы действительно хотите, чтобы первое число было ниже или равно другим трем номерам?

Также чек all(…) >= … не имеет смысла, так как all() возвращает только True или False так, сравнивая его с целым числом, не имеет смысла.

Обратите внимание, что all(is_valid) также вернет True на IP-адреса, такие как 0.0.0.0, поэтому, возможно, вам придется отрегулировать диапазон, который я использовал.

+0

Спасибо, это действительно помогло мне. Извините, что так долго отвечал, был занят. Хотите знать, какие требования для IPv4-адреса? числа должны быть последовательно больше, за исключением первого номера? Нелегко найти точные требования. – eeskonivich

+1

Существуют специальные IP-адреса, но они не являются «недействительными». И нет требования, чтобы число было больше, чем предыдущее. Например, '192.168.0.254' или' 192.168.178.1' являются вполне допустимыми IP-адресами. – xZise

1

Не изобретайте велосипед (если только вы не хотите поддерживать колесо). Вы можете использовать регулярное выражение для проверки адресов 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 
1

Если вы используете Python3, есть встроенный модуль ipaddress, который вы можете использовать.

Что касается неправильного кода, я не считаю, что функция all() делает то, что вы думаете. all() ожидает итерабельность Booleans и возвращает True, если каждый из этих логических значений True.

Чтобы получить, чтобы работать, как вы ожидали, вы, вероятно, хотите что-то вроде

all(addr_piece >= slice_split_address[0] for addr_piece in slice_split_address) 
+0

И с python2 может использовать [IPy] (https://pypi.python.org/pypi/IPy/) – Cesar

0

Как говорили другие, есть лучшие способы сделать это. И ваш алгоритм фактически не проверяет адреса 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 блок, потому что нет необходимости делать это, если, если/Элиф части возврата false.

all(u >= head for u in slice_split_address) 

использует простое выражение генератора, чтобы убедиться, что все элементы в slice_split_address являются> = элемент головки.

Смежные вопросы