Пограничные случаи

Функция my_substr, которую вы реализовали в прошлом уроке, содержит множество ошибок. «Но ведь она прошла проверки!». Да, но в этих проверках не было так называемых пограничных случаев. Функция нормально работала с нормальными аргументами, но как она поведёт себя, если передать ей такие варианты длины?

  • 0.
  • Отрицательное число.
  • Число, превышающее реальный размер строки.

Функция my_substr не рассчитана на такие варианты. Можно подумать, что это не проблема: функция работает в нормальных условиях, и просто не нужно передавать ей «плохие» аргументы. В идеальном мире — да, но в реальном мире ваш код будет запускаться в разных ситуациях, с разными комбинациями условий и данных. Нельзя быть уверенным, что аргументы всегда будут корректными, поэтому нужно учитывать все случаи, в рамках здравого смысла.

Ошибки в пограничных случаях — самая частая причина логических ошибок в программах. Программисты всегда забывают что-нибудь учесть. Такие ошибки часто проявляются не сразу и могут долгое время не приводить к видимым проблемам. Программа продолжает работать, но в какой-то момент обнаруживается, что в результатах есть ошибки. Часто причина в динамической типизации Python.

Умение справляться с такими ошибками приходит с опытом, через постоянные косяки в стиле «ой, забыл проверить на пустую строку!».


Давайте представим себе расширенную функцию my_substr. Она принимает три аргумента: строку, индекс и длину извлекаемой подстроки. Функция возвращает подстроку указанной длины, начиная с указанного индекса. Примеры вызова:

string = 'If I look back I am lost'
print(my_substr(string, 0, 1))  # => 'I'
print(my_substr(string, 3, 6))  # => 'I look'

Прикинем, что может пойти не так. Какие пограничные случаи стоит учитывать:

  • Отрицательная длина извлекаемой подстроки.
  • Отрицательный заданный индекс.
  • Заданный индекс выходит за границу всей строки.
  • Длина подстроки в сумме с заданным индексом выходит за границу всей строки.

В реализации функции каждый пограничный случай будет отдельным куском кода, скорее всего реализованным с помощью if.

Чтобы написать функцию my_substr и защититься от этих случаев, стоит реализовать отдельную функцию, которая будет проверять аргументы на корректность. Займёмся этим в задании.

Задание

Реализуйте функцию-предикат is_arguments_for_substr_correct, которая принимает три аргумента:

  1. строку;
  2. индекс, с которого начинать извлечение;
  3. длину извлекаемой подстроки.

Функция возвращает False, если хотя бы одно из условий истинно:

  • Отрицательная длина извлекаемой подстроки.
  • Отрицательный заданный индекс.
  • Заданный индекс выходит за границу всей строки.
  • Длина подстроки в сумме с заданным индексом выходит за границу всей строки.

В ином случае функция возвращает True.

Не забывайте, что индексы начинаются с 0, поэтому индекс последнего элемента — это «длина строки минус 1».

Пример вызова:

string = 'Sansa Stark'
print(is_arguments_for_substr_correct(string, -1, 3))   # => False
print(is_arguments_for_substr_correct(string, 4, 100))  # => False
print(is_arguments_for_substr_correct(string, 10, 10))  # => False
print(is_arguments_for_substr_correct(string, 11, 1))   # => False
print(is_arguments_for_substr_correct(string, 3, 3))    # => True
print(is_arguments_for_substr_correct(string, 0, 5))    # => True

Нашли ошибку? Есть что добавить? Пулреквесты приветствуютсяhttps://github.com/hexlet-basics

Упражнение доступно только авторизованным пользователям.

Пожалуйста, авторизуйтесь, это необходимо для отслеживания прогресса выполнения уроков. Если у вас ещё нет учётной записи, то сейчас самое время создать аккаунт.