Комбинирование операций и функций

Логические операции — это выражения. Значит, логические операции можно комбинировать с другими выражениями.


Мы хотим проверить чётность числа, то есть кратность двум. В программировании используют такой подход: проверяют остаток от деления на 2:

  • если остаток 0, то число было чётным;
  • если остаток не 0, то число было нечётным.

Остаток от деления — простая, но очень важная концепция в арифметике, алгебре, и даже в теории чисел и криптографии. Идея проста: нужно разделить число на несколько равных групп, и если в конце что-то останется — это и есть остаток от деления.

Делим конфеты поровну между людьми:

  • 7 конфет, 2 человека: 2 x 3 + остаток 1. Значит, 7 не кратно 2.
  • 21 конфету, 3 человека: 3 x 7 + остаток 0. Значит, 21 кратно 3.
  • 19 конфет, 5 человек: 5 x 3 + остаток 4. Значит, 19 не кратно 5.

Оператор % вычисляет остаток от деления (не путайте с делением):

  • 7 % 21
  • 21 % 30
  • 19 % 54

С помощью него напишем функцию проверки чётности:

def is_even(number):
    return number % 2 == 0

print(is_even(10))  # => True
print(is_even(3))   # => False

В одном выражении мы скомбинировали логический оператор == (проверка равенства) и арифметический оператор %.

Приоритет арифметических операций выше логических. Значит, сначала вычисляется арифметическое выражение number % 2, затем результат участвует в логическом сравнении.

По-русски это можно расшифровать так: «вычислить остаток от деления числа number на 2 и сравнить, равен ли остаток нулю, затем вернуть результат проверки равенства».


Другой пример: напишем функцию, которая принимает строку и проверяет, начинается ли эта строка с латинской буквы a.

Алгоритм:

  1. Получим и запишем в переменную первый символ из строки-аргумента.
  2. Сравним, равен ли символ латинской букве a.
  3. Вернём результат.
def is_first_letter_an_a(string):
    first_letter = string[0]
    return first_letter == 'a'

print(is_first_letter_an_a('orange'))  # => False
print(is_first_letter_an_a('apple'))   # => True

Попробуйте проговорить происходящее по-русски, аналогично тому, как мы расшифровывали процесс в примере с is_even в начале урока.


Напомним об извлечении символов из строки с помощью квадратных скобок:

first_name = 'Alexander'

first_name[0]  # 'A'
first_name[1]  # 'l'
first_name[2]  # 'e'
first_name[3]  # 'x'
first_name[4]  # 'a'
first_name[5]  # 'n'
first_name[6]  # 'd'
first_name[7]  # 'e'
first_name[8]  # 'r'

Задание

Сэм решил изучить историю Таргариенов со времени первых людей, но книг было много и информация могла находиться в любой из них. К счастью для Сэма, большинство книг были оцифрованы молодыми мейстерами. Он подумал, что неплохо бы написать функцию, которая анализирует тексты на наличие в них упоминания фамилии Таргариенов.

Для выполнения задания вам потребуется способ, позволяющий отрезать от строки, начиная от её начала, кусок заданной длины. Сделать это легко, используя слегка изменённый вариант операции извлечения символа:

string[i:j]

Здесь i — порядковый номер (индекс) символа, начиная с которого будет производиться “обрезка” строки; j — индекс символа, перед которым отрезок должен закончиться. Длина отрезка составит j - i. Примеры:

print('Winterfell'[0:6])  # => 'Winter'
print('Stark'[0:6])       # => 'Stark'

# берём отрезок, начиная с символа с индексом 2,
# и заканчивая символом с индексом 4
# (т.е. "перед символом с индексом 5")
print('Absolute'[2:5])  # => 'sol'

# начиная с символа с индексом 3
# и не доходя до символа с индексом 3,
# берём пустой отрезок (3 - 3 == 0)
print('Absolute'[3:3])  # => ''

(во втором примере 'Stark'[0:6]) символов получилось меньше, чем мы хотели, ведь в изначальной строке было меньше шести символов).

Есть укороченный синтаксис для этой операции, когда можно не указывать значение i:

string[:n]

В таком случае, по умолчанию подставляется значение 0 — то есть считается, что отрезок берётся от начала строки до символа с индексом n, не включая оный. Поэтому пару примеров выше мы можем переписать так:

print('Winterfell'[:6])  # => 'Winter'
print('Stark'[:6])       # => 'Stark'

И, естественно, вместо чисел можно использовать переменные:

n = 6
print('Winterfell'[:n])  # => 'Winter'
print('Stark'[:n])       # => 'Stark'

Реализуйте функцию has_targaryen_reference, которая принимает на вход строку и проверяет, начинается ли она с Targaryen. Эта функция должна извлекать подстроку такой же длины, как и у слова Targaryen, а затем проверять, равна ли извлечённая подстрока строке Targaryen. Напомню, что индексы начинаются с нуля.

print(has_targaryen_reference(''))           # => False
print(has_targaryen_reference('Targari'))    # => False
print(has_targaryen_reference('targaryen'))  # => False
print(has_targaryen_reference('Targaryen'))  # => True

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

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

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