Перейти к содержанию

432 уроков, 26 библиотек и челлендж «Что выведет код?» — бесплатно, код прямо в браузере

Начать обучение
Урок 8 из 20 Начальный 15 мин 100 XP

in в Python: есть ли элемент в списке

Один оператор вместо цикла с флагом: in задаёт списку вопрос есть ли элемент и отвечает True или False. Разбираем ответ, перевёрнутый not in и коварное сравнение целиком.

Редакция Питоники

Самый частый вопрос к списку звучит не «что лежит на третьем месте», а «есть ли это вообще тут». Был ли товар в корзине, входит ли пользователь в стоп-лист, разрешено ли имя. До знакомства с оператором in такой вопрос решают циклом со счётчиком и условием — пять строк на один вопрос. in делает ту же работу одним выражением. Разберём, как оператор отвечает, как спросить наоборот, где он ищет целиком, а где по частям — и во сколько обходится проверка.

in отвечает True или False

Оператор ставится между искомым значением и списком и возвращает булев ответ — на нём можно сразу печатать и строить условия:

есть ли товар в корзине
cart = ['молоко', 'хлеб', 'сыр']
print('хлеб' in cart)
print('крупа' in cart)
print(40 in [10, 20, 40])
Вывод
True
False
True

Три вопроса — три честных ответа. Оператор in отвечает одним словом: True, если элемент в списке есть, и False, если его там нет. Сам список проверка не меняет: in только спрашивает, а не редактирует. Тип значения не важен — строки и числа список проверяет одинаково.

not in: вопрос наоборот

Обратный вопрос — убедиться, что элемента нет — задаёт оператор not in. Он читается как обычная фраза и избавляет от отрицания результата:

проверка стоп-листа
banned = ['spam', 'troll']
user = 'guest'
print(user not in banned)
banned.append(user)
print(user not in banned)
Вывод
True
False

Гость был вне стоп-листа — True; после добавления через append проверка перевернулась. Список вырос на один элемент, и in это сразу заметил: оператор смотрит в актуальное состояние, а не в снимок на момент записи условия.

Старый способ: цикл с флагом

Приём с циклом до сих пор живёт в чужом коде, поэтому полезно узнавать его в лицо: переменная-флаг стартует с False и включается, если совпадение нашлось:

поиск циклом против одной строки
names = ['анна', 'борис', 'вера']
target = 'борис'
found = False
for name in names:
    if name == target:
        found = True
print(found)
print(target in names)
Вывод
True
True

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

in сравнивает элемент целиком

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

подстрока и элемент рядом
word = 'молоко'
cart = ['молоко', 'хлеб']
print('ло' in word)
print('ло' in cart)
print('молоко' in cart)
Вывод
True
False
True

Слово 'ло' внутри строки нашлось — True. Внутри списка такого элемента нет: там лежат 'молоко' и 'хлеб', а куска 'ло' ни один из них не является — False. Список не заглядывает внутрь своих элементов: он сравнивает каждый с искомым целиком, и совпадение должно быть полным.

Тип важен: строка и число не равны

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

число и его строка — разные вещи
cart = [5, 10, 15]
print(10 in cart)
print('10' in cart)
print(str(10) in ['10'])
Вывод
True
False
True

Число 10 в списке есть, строка '10' — нет: для Python это разные значения, хоть печатаются они одинаково. Если данные пришли строкой, а список хранит числа, проверку нужно готовить заранее — превратить строку в число функцией int или хранить всё в одном типе.

Сколько стоит проверка

Механизм у списка простой: перебор. Чтобы ответить на вопрос, Python по очереди сравнивает элементы с искомым — нашёл на пятой позиции, сделал пять сравнений; не нашёл — прошёл список до конца. На больших данных цена растёт вместе с длиной:

проверка на миллионе элементов
big = list(range(1000000))
print(999999 in big)
print(1234567 in big)
print(len(big))
Вывод
True
False
1000000

Ответы верные, но второй потребовал миллиона сравнений впустую: числа 1234567 в списке нет, и перебор дошёл до конца. Множество на том же вопросе отвечает мгновенно — там поиск устроен через хеш и не зависит от размера. Когда проверок становится много, список стоит превратить во множество — полный разбор скорости в уроке про in у множеств.

in внутри if

Главная работа in — условия. Булев ответ встраивается в if так же естественно, как сравнение чисел:

проверка перед действием
logins = ['anna', 'boris', 'admin']
if 'admin' in logins:
    print('админ на месте')
if 'hacker' not in logins:
    print('чужих нет')
Вывод
админ на месте
чужих нет

Обе ветки сработали: админ нашёлся, чужой не нашёлся. Читается такое условие как обычная фраза — «если админ среди логинов» — и именно в таком виде оператор встречается в реальном коде чаще всего.

Справа стоитЧто проверяет inПример
СписокЦелый элемент'хлеб' in cart
СтрокаПодстроку'ло' in 'молоко'
СловарьКлюч'цена' in goods
МножествоЭлемент, мгновенно'spam' in banned
в словаре in ищет ключи
goods = {'хлеб': 40, 'молоко': 85}
print('хлеб' in goods)
print(40 in goods)
Проверка у словаря отвечает за ключи: 'хлеб' — True, а число 40 — False, хотя именно оно лежит в значениях. Значения проверяют отдельными способами, полный разбор — в уроке про in у словаря.

Проверка принадлежности встала в арсенал: одно выражение вместо цикла с флагом. Следующий шаг — один вызов вместо цикла-счётчика: встроенные min, max и sum считают сумму, минимум и максимум списка одной строкой.

Что выведет код?

Сначала предскажи ответ в голове — это главный навык программиста.

nums = [4, 8, 15]
print(8 in nums)
print('8' in nums)
print(16 not in nums)
word = 'кот'
words = ['кот', 'код']
print('о' in word)
print('о' in words)
cart = ['чай', 'кофе']
order = 'кекс'
if order not in cart:
    cart.append(order)
print(len(cart))
print(order in cart)
Проверь себя
0 / 6

1. Что вернёт выражение 'хлеб' in ['молоко', 'хлеб', 'сыр']?

2. Что вернёт 'ло' in ['молоко', 'хлеб']?

3. Что вернёт '10' in [10]?

4. Как убедиться, что элемента в списке нет?

5. Как список отвечает на проверку in внутри?

6. Что напечатает код: banned = ['spam']; banned.append('troll'); print('troll' not in banned)?

Карточки терминов
Запомнено: 0 / 7
Практика

Даны логины logins = ['anna', 'boris', 'vera'] и проверяемое имя login = 'boris'. Напечатайте три строки: есть ли login в списке, нет ли его в списке и входит ли фрагмент 'ris' в список логинов.

practice.py
Вопросы и ответы по уроку

Что делает оператор in в Python?

Проверяет принадлежность: значение in коллекция возвращает True, если элемент найден, и False, если нет. У списка он сравнивает элементы целиком, у строки ищет подстроку, у словаря проверяет ключи, у множества отвечает мгновенно через хеш. Сама коллекция при проверке не меняется.

Урок 9 раздела Списки: агрегаты

Как проверить, что элемента нет в списке?

Оператором not in: if user not in banned вернёт True, когда элемента нет. Писать отрицание вручную (not user in banned) можно, но not in читается естественнее и является стандартным способом.

Почему in не находит часть слова в списке?

Потому что список сравнивает элементы целиком: 'ло' in ['молоко'] — это False, среди элементов нет точного значения 'ло'. Подстроки умеет искать in у самой строки: 'ло' in 'молоко' — True. Чтобы найти элементы, содержащие фрагмент, нужен цикл с проверкой фрагмента внутри каждого элемента.

Поиск в строках: find, rfind и in

Быстро ли работает проверка in у списка?

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

Урок 5 раздела Множества: мгновенный in

Понравился урок? Сошлитесь на него

«Оператор in отвечает одним словом: True, если элемент в списке есть, и False, если его там нет.»

Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.

TelegramVK

Что дальше

Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.

Похожие уроки по темам

Подобраны автоматически по пересечению тем и ключевых слов.