Логические выражения и операторы
Часто в реальной жизни мы соглашаемся с каким-либо утверждением или отрицаем его. Например, если вам скажут, что сумма чисел 3 и 5 больше 7, вы согласитесь, скажете: «Да, это правда». Если же кто-то будет утверждать, что сумма трех и пяти меньше семи, то вы расцените такое утверждение как ложное.
Подобные фразы предполагают только два возможных ответа – либо «да», когда выражение оценивается как правда/истина, либо «нет», когда утверждение оценивается как ошибочное/ложное. В программировании и математике если результатом вычисления выражения может быть лишь истина или ложь, то такое выражение называется логическим.
Например, выражение 4 > 5 является логическим, так как его результатом является либо правда, либо ложь. Выражение 4 + 5 не является логическим, так как результатом его выполнения является число.
На позапрошлом уроке мы познакомились с тремя типами данных – целыми и вещественными числами, а также строками. Сегодня введем четвертый – логический тип данных (тип bool ). Его также называют булевым. У этого типа всего два возможных значения: True (правда) и False (ложь).
>>> a = True >>> type(a) >>> b = False >>> type(b)
Здесь переменной a было присвоено значение True , после чего с помощью встроенной в Python функции type() проверен ее тип. Интерпретатор сообщил, что это переменная класса bool . Понятия «класс» и «тип данных» в данном случае одно и то же. Переменная b также связана с булевым значением.
В программировании False обычно приравнивают к нулю, а True – к единице. Чтобы в этом убедиться, можно преобразовать булево значение к целочисленному типу:
>>> int(True) 1 >>> int(False) 0
Возможно и обратное. Можно преобразовать какое-либо значение к булевому типу:
>>> bool(3.4) True >>> bool(-150) True >>> bool(0) False >>> bool(' ') True >>> bool('') False
И здесь работает правило: всё, что не 0 и не пустота, является правдой.
Логические операторы
Говоря на естественном языке (например, русском) мы обозначаем сравнения словами «равно», «больше», «меньше». В языках программирования используются специальные знаки, подобные тем, которые используются в математике: > (больше), < (меньше), >= (больше или равно),
Не путайте операцию присваивания значения переменной, обозначаемую в языке Python одиночным знаком «равно», и операцию сравнения (два знака «равно»). Присваивание и сравнение – разные операции.
>>> a = 10 >>> b = 5 >>> a + b > 14 True >>> a < 14 - b False >>> a >> a != b True >>> a == b False >>> c = a == b >>> a, b, c (10, 5, False)
В данном примере выражение c = a == b состоит из двух подвыражений. Сначала происходит сравнение ( == ) переменных a и b . После этого результат логической операции присваивается переменной c . Выражение a, b, c просто выводит значения переменных на экран.
Сложные логические выражения
Логические выражения типа kbyte >= 1023 являются простыми, так как в них выполняется только одна логическая операция. Однако, на практике нередко возникает необходимость в более сложных выражениях. Может понадобиться получить ответа «Да» или «Нет» в зависимости от результата выполнения двух простых выражений. Например, «на улице идет снег или дождь», «переменная news больше 12 и меньше 20».
В таких случаях используются специальные операторы, объединяющие два и более простых логических выражения. Широко используются два оператора – так называемые логические И (and) и ИЛИ (or).
Чтобы получить True при использовании оператора and , необходимо, чтобы результаты обоих простых выражений, которые связывает данный оператор, были истинными. Если хотя бы в одном случае результатом будет False , то и все сложное выражение будет ложным.
Чтобы получить True при использовании оператора or , необходимо, чтобы результат хотя бы одного простого выражения, входящего в состав сложного, был истинным. В случае оператора or сложное выражение становится ложным лишь тогда, когда ложны оба составляющие его простые выражения.
Допустим, переменной x было присвоено значение 8 ( x = 8 ), переменной y присвоили 13 ( y = 13 ). Логическое выражение y < 15 and x >8 будет выполняться следующим образом. Сначала выполнится выражение y < 15 . Его результатом будет True . Затем выполнится выражение x >8 . Его результатом будет False . Далее выражение сведется к True and False , что вернет False .
>>> x = 8 >>> y = 13 >>> y < 15 and x >8 False
В случае с оператором or второе простое выражение проверяется, если первое вернуло ложь, и не проверяется, если уже первое вернуло истину. Так как для истинности всего выражения достаточно единственного True , неважно по какую сторону от or оно стоит.
>>> y < 15 or x >8 True
В языке Python есть еще унарный логический оператор not , то есть отрицание. Он превращает правду в ложь, а ложь в правду. Унарный он потому, что применяется к одному выражению, стоящему после него, а не справа и слева от него как в случае бинарных and и or .
>>> not y < 15 False
>>> a = 5 >>> b = 0 >>> not a False >>> not b True
Число 5 трактуется как истина, отрицание истины дает ложь. Ноль приравнивается к False . Отрицание False дает True .
Практическая работа
- Присвойте двум переменным любые числовые значения.
- Используя переменные из п. 1, с помощью оператора and составьте два сложных логических выражения, одно из которых дает истину, другое – ложь.
- Аналогично выполните п. 2, но уже с оператором or .
- Попробуйте использовать в логических выражениях переменные строкового типа. Объясните результат.
- Напишите программу, которая запрашивала бы у пользователя два числа и выводила бы True или False в зависимости от того, больше первое число второго или нет.
Примеры решения и дополнительные уроки в pdf-версии курса
X Скрыть Наверх
Python. Введение в программирование
Что означает оператор or в python
В языке Python операторы and и or, как вы и ожидали, выполняют булевы операции, но они не возвращают булевы значения: результатом всегда является значение одного из операндов.
Пример 2.16. Оператор and
>>> 'a' and 'b' 'b' >>> '' and 'b' '' >>> 'a' and 'b' and 'c' 'c'
При использовании оператора and, значения вычисляются в булевом контексте слева напрво. Значения 0, '', [], (), <> и None являются ложью, все остальное является истиной [3] . Если у and оба операнда являются истиной, результатом будет последнее значение. В данном случае вычисляется выражение 'a', которое является истиной, затем 'b', которое также является истиной, и возвращается 'b'. | |
Если какой-либо из операндов является ложью, результатом будет первое такое значение. В данном случает '' — первое значение, являющееся ложью. | |
Все значения являются истиной, так что в результате мы получаем последнее — 'c'. |
Пример 2.17. Оператор or
>>> 'a' or 'b' 'a' >>> '' or 'b' 'b' >>> '' or [] or <> <> >>> def sidefx(): . print "in sidefx()" . return 1 >>> 'a' or sidefx() 'a'
Как и для and опреранды or вычисляются в булевском контексте слева направо. Если операнд является истиной, or немедленно возвращает результат. В данном случае 'a' — первое истинное значение. | |
or вычисляет выражение '', которое является ложью, затем 'b', которое является истиной, и возвращает 'b'. | |
Если все значения являются ложью, or возвращает последнее. or вычисляет '' (ложь), [] (ложь), затем <> (ложь) и возвращает <>. | |
Обратите внимание, что or вычисляет операнды до тех пор, пока не найдет истинное значение, остальное игнорируется. Это имеет значение, когда вычисление операнда дает сторонние эффекты. В данном случае функция sidefx не вызывается, так как для получения результата выражения с опереатором or достаточно того, что первый операнд, 'a', является истиной. |
Если вы используете C, то, наверное, знакомы с выражением bool ? a : b, которое дает a, если bool является истиной, b, если bool ложно. Благодаря особенностям работы операторов and и or в Python, вы можете достигнуть анологичного эффекта.
Пример 2.18. Прием с and-or
>>> a = "first" >>> b = "second" >>> 1 and a or b 'first' >>> 0 and a or b 'second'
Синтаксис bool ? a : b в языке Python выглядит похоже. Все выражение вычисляется слева направо, так что оператор and применяется первым. 1 and 'first' дает 'first', затем 'first' or 'second' дает 'first'. | |
0 and 'first' дает 0, тогда 0 or 'second' дает 'second'. |
Однако, так как такое выражение выполняет обычные логические операции, а не является специальной конструкцией языка, существует очень важная разница между приемом с and-or в языке Python и конструкцией bool ? a : b в C. Если значение a является ложью, это прием не будет работать так как вы могли ожидать. (Вы можете сказать, что обожгись на этом? Более одного раза?)
Пример 2.19. Когда прием с and-or не работает
>>> a = "" >>> b = "second" >>> 1 and a or b 'second'
Так как a — пустая строка, которую Python считает ложью в булевом контексте, 1 and '' дает '', а '' or 'second' дает 'second'. Ой! Это не то, что мы хотели получить. |
Прием с and-or, bool and a or b, не будет работать так же, как конструкция bool ? a : b в C, если a является ложью. |
Для безопасного использования приема с and-or необходимо сделать так, чтобы a всегда было истинным. Один из самых распространенных способо это сделать — заменить a на [a] и b на [b], тогда первый элемент получаемого списка будет либо a, либо b.
Пример 2.20. Безопасное использование приема с and-or
>>> a = "" >>> b = "second" >>> (1 and [a] or [b])[0] ''
Так как выражение [a] является непустым списком, оно никогда не будет ложно. Даже если a равно 0, '' или другому значению, являющемуся ложью, список [a] всегда будет являться истиной, потому что содержит один элемент. |
Кажется, этот прием не стоит того, чтобы его использовать. В конце концов вы всегда можете воспользоваться интсрукцией if. Тогда зачем вся эта суета? Конечно, в большинстве случаев выбирая между двумя константами вы можете использовать простой синтаксис и не беспокоиться, потому что значение a всегда будет истинным. И даже если придется использовать более сложный синтакс, на это могут найтись весские причины: в некоторых случаях в языке Python использование инструкции if не допускается, например в lambda-функциях.
- В Python Cookbook обсуждаются альтернативы приему с and-or.
[3] Ну, почти все. По умолчанию экземпляры классов являются истиной, но вы можете определить специальные методы в классе, чтобы его экземпляры могли быть ложью. Вы узнаете все о классах и специальных методах в главе 3.
Copyright © 2000, 2001, 2002 Марк Пилгрим
Copyright © 2001, 2002 Перевод, Денис Откидач
Python: Логические операторы
Мы уже умеем писать функции, которые проверяют одиночные условия. А в этом уроке научимся строить составные условия.
Предположим, что сайт при регистрации требует, чтобы пароль был длиннее восьми символов и содержал хотя бы одну заглавную букву. Попробуем написать два отдельных логических выражения и соединим их специальным оператором «И»:
Пароль длиннее 8 символов И пароль содержит хотя бы одну заглавную букву
Вот функция, которая принимает пароль и говорит, соответствует ли он условиям ( True ) или не соответствует ( False ):
def has_capital_letter(string): # Проверяет наличие хотя бы одной заглавной буквы в строке def is_correct_password(password): length = len(password) return length > 8 and has_capital_letter(password) print(is_correct_password('Qwerty')) # => False print(is_correct_password('Qwerty1234')) # => True print(is_correct_password('qwerty1234')) # => False
and — означает «И». В математической логике это называют конъюнкцией. Все выражение считается истинным, если истинен каждый операнд — каждое из составных выражений. Иными словами, and означает «и то, и другое». Приоритет этого оператора ниже, чем приоритет операторов сравнения. Поэтому выражение has_capital_letter(password) and length > 8 тоже правильно отрабатывает без скобок.
Кроме and часто используется оператор or — «ИЛИ» (дизъюнкция). Он означает «или то, или другое, или оба». Выражение a or b считается истинным, если хотя бы один из операндов или одновременно все — истинные. В другом случае выражение ложное.
Операторы можно комбинировать в любом количестве и любой последовательности. Если в коде одновременно встречаются and и or , то приоритет задают скобками. Ниже пример расширенной функции, которая определяет корректность пароля:
def has_capital_letter(string): # Проверяет наличие хотя бы одной заглавной буквы в строке def has_special_chars(string): # Проверяет содержание специальных символов в строке def is_strong_password(password): length = len(password) # Скобки задают приоритет. Понятно, что к чему относится. return (length > 8 and has_capital_letter(password)) and has_special_chars(password)
Теперь представим, что мы хотим купить квартиру, которая удовлетворяет таким условиям: площадь от 100 квадратных метров и больше на любой улице ИЛИ площадь от 80 квадратных метров и больше, но на центральной улице Main Street .
Напишем функцию, которая проверит квартиру. Она принимает два аргумента: площадь — число и название улицы — строку:
def is_good_apartment(area, street): return area >= 100 or (area >= 80 and street == 'Main Street') print(is_good_apartment(91, 'Queens Street')) # => False print(is_good_apartment(78, 'Queens Street')) # => False print(is_good_apartment(70, 'Main Street')) # => False print(is_good_apartment(120, 'Queens Street')) # => True print(is_good_apartment(120, 'Main Street')) # => True print(is_good_apartment(80, 'Main Street')) # => True
Область математики, в которой изучаются логические операторы, называется булевой алгеброй. Ниже увидите таблицы истинности — по ним можно определить, каким будет результат, если применить оператора:
И and
A | B | A and B |
---|---|---|
True | True | True |
True | False | False |
False | True | False |
False | False | False |
ИЛИ or
A | B | A or B |
---|---|---|
True | True | True |
True | False | True |
False | True | True |
False | False | False |
Задание
Реализуйте функцию is_leap_year() , которая принимает год в форме числа и определяет является ли он високосным или нет. Год будет високосным, если он кратен (то есть делится без остатка) 400 или он одновременно кратен 4 и не кратен 100. Как видите, в определении уже заложена вся необходимая логика, осталось только переложить её на код:
is_leap_year(2018) # false is_leap_year(2017) # false is_leap_year(2016) # true
Кратность можно проверять так:
# % - возвращает остаток от деления левого операнда на правый # Проверяем что number кратен 10 number % 10 == 0 # Проверяем что number не кратен 10 number % 10 != 0
Упражнение не проходит проверку — что делать?
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
- Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Мой код отличается от решения учителя
Это нормально , в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Прочитал урок — ничего не понятно
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Полезное
- Булева алгебра
- Логическое «И»
- Логическое «ИЛИ»
Определения
- Логические операторы — операторы «И» ( and ), ИЛИ ( or ), позволяющие создавать составные логические условия.
Понимание работы логических операций and, or и not
Важно! Операторы and и or закорачивают вычисление своих операндов (т.е. используют замыкания): правый операнд вычисляется лишь в том случае, если его значение необходимо для получения истинного значения в операциях and или or . Другими словами, замыкания в логических операциях используются для запуска второй части или последующих частей логического выражения только в том случае, если это актуально!
- or - оценивает второй аргумент, только если первый равен False . Если какой либо операнд в цепочке or является истиной, немедленно возвращается результат - первое истинное значение.
- and - оценивает второй аргумент, только если первый равен True . Если в цепочке and все операнды являются истиной, результатом будет последнее значение. А если какой-либо из операндов является False , результатом будет первое ложное значение.
- not имеет более низкий приоритет, чем операторы сравнения, так not a == b интерпретируется как not (a == b) , а выражение a == not b вовсе является синтаксической ошибкой. Единственный логический оператор с одним аргументом. Он принимает один аргумент x и возвращает противоположный результат: False для истинного значения и True для ложного значения.
Операторы and и or не приводят свои результаты принудительно к значениям True или False , а возвращают один из своих операндов. Такой подход позволяет использовать эти операторы в более общих, а не только булевых операциях. Если другие операторы, прежде чем выполнить операцию, вычисляют все свои операнды, то в случае операторов and и or с их семантикой закорачивания необходимость вычисления правого операнда определяется результатом вычисления левого.
Из булевых операторов, not имеет самый высокий приоритет, а or самый низкий, так что A and not B or C эквивалентно (A and (not B)) or C . Как всегда, скобки могут быть использованы для выражения желаемого приоритета в операциях.
Логические операции, упорядоченные по приоритету выполнения:
- not x - если x ложно, то возвращается True , иначе False .
- x and y - если x ложно, то возвращается x , иначе у .
- x or y - если x ложно, то возвращается у , иначе x
Объяснение работы замыкания c оператором and :
a = 'a' b = 'b' c = 'c' >>> a and b # 'b' >>> '' and b # '' >>> a and b and c # 'c'
Пояснения к примеру выше с оператором and :
- Оператор and вычисляет значения в булевом контексте слева направо. Значения 0 , '' , [] , () , <> и None являются ложью, все остальное является истиной. Если у and оба операнда являются истиной, результатом будет последнее значение.
- Если какой-либо из операндов является ложью, результатом будет первое такое значение. В данном случает это '' - пустая строка, первое значение которое является ложью.
- Все значения являются истиной, так что в результате мы получаем последнее c .
Объяснение работы замыкания c оператором or :
a = 'a' b = 'b' >>> a or b # 'a' >>> '' or b # 'b' >>> '' or [] or <> # <> >>> def func(): . return 1 >>> a or func() # 'a'
Пояснения к примеру выше с оператором or :
- Оператор or вычисляет значения в булевом контексте слева направо. Если операнд является истиной, or немедленно возвращает результат. В данном случае a , первое истинное значение.
- or вычисляет выражение '' , которое является ложью, затем b, которое является истиной, и возвращает его значение.
- Если все значения являются ложью, or возвращает последнее.
- Обратите внимание, что or вычисляет операнды до тех пор, пока не найдет истинное значение, остальное игнорируется. Это имеет значение, когда вычисление операнда дает сторонние эффекты. В данном случае функция func() не вызывается, так как для получения результата выражения с оператором or достаточно того, что первый операнд a является истиной.
Другие примеры с and и or :
>>> a = 'one' >>> b = 'two' >>> 1 and a or b # 'one' >>> 0 and a or b # 'two' >>> a = '' >>> b = 'two' # 'a' - пустая строка, которую Python считает ложью, # следовательно 1 and '' дает '', а '' or 'two' дает 'two'. >>> 1 and a or b # 'two'
Практическое использование замыканий and и or в кодовой базе.
Внимание! Замыкания в операциях and и or можно использовать с пользой в вычислениях для экономии ресурсов, сокращения времени выполнения и т.д., только будьте осторожны! Необходимо четко понимать как работают замыкания в операторах and и or .
- Экономия ресурсов и времени выполнения при помощи and ;
- Проверка предварительных условий перед выражением;
- Определение значения по умолчанию при помощи or ;
- Пример использования замыканий в функциях all() и any() .
Экономия ресурсов и времени выполнения при помощи and .
Рассмотрим реальный пример из модуля base64 стандартной библиотеки Python, который использует замыкание в оператора if . Исследуем функцию b64decode , которая берет строку (или объект, подобный байтам) и декодирует ее:
# взято из Lib/base64.py def b64decode(s, altchars=None, validate=False): """Decode the Base64 encoded bytes-like object or ASCII string s. [docstring cut for brevity] """ s = _bytes_from_decode_data(s) if altchars is not None: altchars = _bytes_from_decode_data(altchars) assert len(altchars) == 2, repr(altchars) s = s.translate(bytes.maketrans(altchars, b'+/')) # использование замыкания с оператором `and` if validate and not re.fullmatch(b'[A-Za-z0-9+/]*=', s): raise binascii.Error('Non-base64 digit found') return binascii.a2b_base64(s)
Смотрим на оператор if , который помечен комментарием. В условии сначала проверяется аргумент validate , а только потом результат работы функции re.fullmatch() . Аргумент validate сообщает функции, хочет ли пользователь вообще проверять строку, которую нужно декодировать. Обратите внимание, что если validate=False то сопоставление регулярного выражения не запускается (срабатывает замыкание). Если порядок операндов поменять, то результат остался такой же, но было бы потрачено гораздо больше времени.
Проверка предварительных условий перед выражением.
Другой типичный шаблон использования замыканий проявляется, когда перед определенной операцией, которая может вызвать исключение, нужно что-то проверить.
Допустим есть последовательность и нужно взять элемент по индексу, но последовательность может оказаться пустой или ее длина может быть меньше индекса. Например:
>>> lst = [0, 1, 2] >>> lst[3] # Traceback (most recent call last): # File "", line 1, in # IndexError: list index out of range
Используем проверку предварительных условий:
>>> lst = [0, 1, 2] >>> if lst and len(lst) >=3: . lst[3]
Здесь, в условии сначала проверяется что список НЕ пустой и только после этого вычисляется длинна этого списка. Если список пустой, то его длина проверяться не будет и условие if завершиться.
Еще один пример из модуля enum :
# взято из Lib/enum.py def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1): """ Convenience method to create a new Enum class. """ # [сокращено для краткости] # special processing needed for names? if isinstance(names, str): names = names.replace(',', ' ').split() # смотрим на следующие условие if isinstance(names, (tuple, list)) and names and isinstance(names[0], str): original_names, names = names, [] last_values = [] # [сокращено для краткости]
Более длинный оператор if содержит три выражения, разделенных операторами and , и первые два выражения нужны для того, чтобы убедиться, можно ли безопасно выполнить последнее.
- isinstance(names, (tuple, list)) - проверяет, является ли names кортежем или списком. Если не является то условие завершается.
- далее names проверяется пусто оно или нет. Если элементов нет то условие завершается.
- если names не пустой, то можно безопасно выполнить последнюю проверку, связанную с индексацией names[0] , а именно isinstance(names[0], str) .
Определение значения по умолчанию при помощи or .
Замыкание с помощью логического оператора or может использоваться для присвоения переменным значений по умолчанию. Вот пример:
# test.py greet = input("Ваше имя >> ") or "незнакомец" print(f"Привет, greet>!") # $python3 -i test.py # Ваше имя >> # Привет, незнакомец!
Если запустить этот пример и ничего не вводя нажать Enter, то получим вывод "Привет, незнакомец!". Что тут происходит? Если ничего не вводить и нажать Enter, то функция input() вернет пустую строку '' , что является False . Следовательно, оператор or видит ложное значение слева и должен оценить правый операнд. Для определения окончательное значение выражения or оценивает правый операнд и если он True , то возвращает его значение.
Еще пример присвоения значение по умолчанию (используя or ) для изменяемого аргумента из стандартной библиотеки Python.
# взято из Lib/cgitb.py class Hook: """A hook to replace sys.excepthook that shows tracebacks in HTML.""" def __init__(self, display=1, logdir=None, context=5, file=None, format="html"): self.display = display # send tracebacks to browser if true self.logdir = logdir # log tracebacks to files if not None self.context = context # number of source code lines per frame self.file = file or sys.stdout # self.format = format
Этот код взят из модуля cgitb и определяет sys.stdout как значение по умолчанию для переменной self.file . Определение функции __init__ имеет file=None в качестве ключевого аргумента, так почему бы просто не написать file=sys.stdout ?
Проблема в том, что sys.stdout может быть изменяемым объектом, поэтому использование file=sys.stdout в качестве ключевого аргумента со значением по умолчанию не будет работать так, как ожидается. Это легче продемонстрировать со списком в качестве аргумента по умолчанию, хотя принцип тот же:
>>> def addend(val, l=[]): . l.append(val) . print(l) >>> addend(3, [1, 2]) # [1, 2, 3] >>> addend(5) # [5] >>> addend(5) # [5, 5] >>> addend(5) # [5, 5, 5]
Обратите внимание на три последовательных вызова addend(5) . Ожидается, что вызов addend(5) со значением по умолчанию l=[] будет вести себя одинаково, но т.к. список является изменяемым объектом, то вызовы добавляют значения val к значению по умолчанию [] , при этом список растет! Дополнительно смотрите материал "Список Python как аргумент по умолчанию".
Пример использования замыканий or и and в функциях all() и any() .
Если в выражении генератора использовать оператор моржа := , и принимать во внимание тот факт, что функции all() и any() также используют замыкания, то можно использовать следующую конструкцию для извлечения первого истинного элемента.
any(predicate(witness := item) for item in items)
Другими словами, если какой-либо элемент item удовлетворяет условию в функции predicate() , то переменная witness сохранит его значение!
Например, если последовательность содержит много целых чисел, как выяснить, есть ли там какие-либо нечетные числа, и как вывести первое из них?
items = [14, 16, 18, 20, 35, 41, 100] any_found = False for item in items: any_found = item % 2 if any_found: print(f"Найдено нечетное число item>.") break
Теперь все это сравним со следующим кодом:
>>> items = [14, 16, 18, 20, 35, 41, 100] >>> is_odd = lambda x: x % 2 >>> if any(is_odd(witness := item) for item in items): . print(f"Найдено нечетное число witness>.") # Найдено нечетное число 35.