← Назад к вопросам

Проверка валидности IP адреса

2.0 Middle🔥 141 комментариев
#Теория тестирования

Условие

Напишите функцию, которая проверяет, является ли строка валидным IPv4 адресом.

Пример

Вход: 192.168.1.1 Выход: true

Вход: 256.1.1.1 Выход: false

Вход: 192.168.1 Выход: false

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Решение

Понимание задачи

Проверить валидность IPv4 адреса. Требования:

  • Ровно 4 части (октета), разделённые точками
  • Каждая часть — число от 0 до 255
  • Нет пустых частей или символов кроме цифр и точек

Оптимальный алгоритм: Split + Валидация

def is_valid_ipv4(ip):
    """
    Проверяет валидность IPv4 адреса.
    """
    parts = ip.split('.')
    
    # Должно быть ровно 4 части
    if len(parts) != 4:
        return False
    
    for part in parts:
        # Часть не должна быть пустой
        if not part:
            return False
        
        # Все символы должны быть цифрами
        if not part.isdigit():
            return False
        
        # Значение должно быть от 0 до 255
        num = int(part)
        if num < 0 or num > 255:
            return False
        
        # Нет ведущих нулей (кроме одного нуля)
        if len(part) > 1 and part[0] == '0':
            return False
    
    return True

Как это работает

Пример 1: 192.168.1.1

Шаг 1: Split -> ['192', '168', '1', '1'] Шаг 2: Длина = 4 ✓ Шаг 3: Проверка каждой части:

  • '192': все цифры ✓, 192 <= 255 ✓
  • '168': все цифры ✓, 168 <= 255 ✓
  • '1': все цифры ✓, 1 <= 255 ✓
  • '1': все цифры ✓, 1 <= 255 ✓ Результат: True

Пример 2: 256.1.1.1

Шаг 1: Split -> ['256', '1', '1', '1'] Шаг 2: Длина = 4 ✓ Шаг 3: Проверка:

  • '256': все цифры ✓, но 256 > 255 ✗ Результат: False

Сложность

  • Временная: O(n) — где n длина строки
  • Пространственная: O(1) — постоянное количество частей (4)

Расширенная версия с обработкой edge cases

def is_valid_ipv4_advanced(ip):
    """
    Проверяет IPv4 с дополнительной обработкой ошибок.
    """
    # Проверка типа входных данных
    if not isinstance(ip, str):
        return False
    
    # Пустая строка
    if not ip or ip.startswith('.') or ip.endswith('.'):
        return False
    
    # Слишком короткая строка
    if len(ip) < 7:  # Минимум: 1.1.1.1
        return False
    
    parts = ip.split('.')
    
    if len(parts) != 4:
        return False
    
    for part in parts:
        # Пустая часть
        if not part:
            return False
        
        # Содержит только цифры
        if not part.isdigit():
            return False
        
        # Ведущие нули (кроме '0')
        if len(part) > 1 and part[0] == '0':
            return False
        
        # Значение в диапазоне
        num = int(part)
        if num > 255:
            return False
    
    return True

Тестирование

# Валидные IPv4
assert is_valid_ipv4('192.168.1.1') == True
assert is_valid_ipv4('0.0.0.0') == True
assert is_valid_ipv4('255.255.255.255') == True
assert is_valid_ipv4('127.0.0.1') == True
assert is_valid_ipv4('10.0.0.1') == True

# Невалидные IPv4
assert is_valid_ipv4('256.1.1.1') == False
assert is_valid_ipv4('192.168.1') == False
assert is_valid_ipv4('192.168.1.1.1') == False
assert is_valid_ipv4('192.168.01.1') == False  # Ведущий ноль
assert is_valid_ipv4('192.168.-1.1') == False  # Отрицательное
assert is_valid_ipv4('192.168.a.1') == False  # Не цифры
assert is_valid_ipv4('.192.168.1.1') == False
assert is_valid_ipv4('192.168.1.1.') == False
assert is_valid_ipv4('') == False
assert is_valid_ipv4('...') == False

Альтернативные подходы

Способ 1: Регулярное выражение

import re

def is_valid_ipv4_regex(ip):
    pattern = r'^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}' \
              r'([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$'
    return bool(re.match(pattern, ip))
  • Одна строка
  • Сложнее для понимания
  • O(n) время

Способ 2: Try-except с socket (неоптимально)

import socket

def is_valid_ipv4_socket(ip):
    try:
        socket.inet_aton(ip)
        return True
    except socket.error:
        return False
  • Простой способ
  • Зависит от стандартной библиотеки
  • Может быть медленнее

Граничные случаи

# Граничные значения
assert is_valid_ipv4('0.0.0.0') == True
assert is_valid_ipv4('255.255.255.255') == True
assert is_valid_ipv4('256.0.0.0') == False
assert is_valid_ipv4('255.255.255.256') == False

# Ведущие нули
assert is_valid_ipv4('192.168.01.1') == False
assert is_valid_ipv4('0.0.0.0') == True  # Один ноль OK
assert is_valid_ipv4('00.0.0.0') == False

# Неправильное количество частей
assert is_valid_ipv4('192.168.1') == False
assert is_valid_ipv4('192.168.1.1.1') == False

# Специальные символы
assert is_valid_ipv4('192.168.1.1a') == False
assert is_valid_ipv4('192.168.1.-1') == False
assert is_valid_ipv4('192 .168.1.1') == False

Выводы

  • Split + валидация — простое и понятное решение
  • O(n) время, O(1) доп. память — эффективно
  • Ключевые проверки: количество частей, диапазон 0-255, ведущие нули
  • Для QA: граничные значения, ведущие нули, спецсимволы, неправильное количество частей