Секреты логических операторов в Python (2024)

Логические операции играют важную роль в программировании. Они используются для создания условных конструкций и составления сложных алгоритмов. В Python для выполнения логических операций используются логические операторы:

  • not— логическое отрицание

  • and— логическое умножение

  • or— логическое сложение

В этой статье мы поговорим о неочевидных деталях и скрытых особенностях работы логических операторов в Python.

Таблицы истинности логических операторов

Мы привыкли к тому, что обычно в языках программирования логические операторы возвращают значения True или False согласно своим таблицам истинности.

Таблица истинности оператора not:

a

not a

False

True

True

False

Таблица истинности оператора and:

a

b

a and b

False

False

False

False

True

False

True

False

False

True

True

True

Таблица истинности оператора or:

a

b

a or b

False

False

False

False

True

True

True

False

True

True

True

True

Когда операндами логических операторов являются объекты True и False, работа логических операторов в Python также соответствует данным таблицам истинности.

Приведенный ниже код:

print(not True)print(not False)print(False and True)print(True and True)print(False or True)print(False or False)

выводит:

FalseTrueFalseTrueTrueFalse

Однако Python не ограничивает нас только значениями True и False в качестве операндов логических операторов. Операндами операторов not, and и or могут быть объекты любых других типов данных.

Понятия truthy и falsy

Одной из важных особенностей языка Python является концепция truthy и falsy объектов. Любой объект в Python может быть оценен как True или False. При этом объекты, которые оцениваются как True, называются truthy объектами, а объекты, которые оцениваются как Falsefalsy объектами.

К встроенным falsy объектам относятся:

Другие объекты встроенных типов данных относятся к truthy объектам. Экземпляры пользовательских классов по умолчанию также являются truthy объектами.

Чтобы привести объекты к значению True или False, используется встроенная функция bool().

Приведенный ниже код:

# falsy объектыprint(bool(False))print(bool(None))print(bool(0))print(bool(0.0))print(bool([]))print(bool(''))print(bool({}))#truthy объектыprint(bool(True))print(bool(123))print(bool(69.96))print(bool('beegeek'))print(bool([4, 8, 15, 16, 23, 42]))print(bool({1, 2, 3}))

выводит:

FalseFalseFalseFalseFalseFalseFalseTrueTrueTrueTrueTrueTrue

Концепция truthy и falsy объектов в Python позволяет работать с условным оператором в более простой манере.

Например, приведенный ниже код:

if len(data) > 0: ...if value == True: ...if value == False: ... 

можно переписать в виде:

if data: ... if value: ... if not value: ...

На картинке ниже представлены примеры упрощенной записи условного оператора с различными объектами Python согласно концепции truthy и falsy объектов:

Секреты логических операторов в Python (1)

Оператор not

Как мы уже знаем, операндом оператора not может быть объект любого типа. Если операнд отличен от значений True и False, он оценивается в соответствии с концепцией truthy и falsy объектов. При этом результатом работы оператора not всегда является значение True или False.

Приведенный ниже код:

print(not False)print(not None)print(not 0)print(not 0.0)print(not [])print(not '')print(not {})

выводит:

TrueTrueTrueTrueTrueTrueTrue

Приведенный ниже код:

print(not True)print(not 123)print(not 69.96)print(not 'beegeek')print(not [4, 8, 15, 16, 23, 42])print(not {1, 2, 3})

выводит:

FalseFalseFalseFalseFalseFalse

Операторы and и or

Операндами операторов and и or, как и в случае с not, могут быть объекты любых типов данных. По аналогии с оператором not можно предположить, что результатом работы логических операторов and и or также является значение True или False. Однако на самом деле данные операторы возвращаютодин из своих операндов. Какой именно — зависит от самого оператора.

Приведенный ниже код:

print(None or 0)print(0 or 5)print('beegeek' or None)print([1, 2, 3] or [6, 9])print(1 or 'beegeek' or None)print(0.0 or 'habr' or {'one': 1})print(0 or '' or [6, 9])print(0 or '' or [])print(0 or '' or [] or {})

выводит:

05beegeek[1, 2, 3]1habr[6, 9][]{}

Как мы видим, оператор or оценивает каждый свой операнд как truthy или falsyобъект, однако возвращает не значение True или False, а сам объект по определенному правилу — первыйtruthy объект либо последний объект, еслиtruthyобъекты в логическом выражении не найдены.

Аналогично дело обстоит с оператором and.

Приведенный ниже код:

print(None and 10)print(5 and 0.0)print('beegeek' and {})print([1, 2, 3] and [6, 9])print(1 and 'beegeek' and None)print('habr' and 0 and {'one': 1})print(10 and [6, 9] and [])

выводит:

None0.0{}[6, 9]None0[]

Операторandвозвращает первыйfalsy объект либо последний объект, еслиfalsy объекты в логическом выражении не найдены.

Логические операторы ленивы

Логические операторы в Python являются ленивыми. Это означает, что возвращаемый операнд вычисляется путем оценки истинности всех операндов слева направо до тех пор, пока это остается актуальным:

  • если левый операндоператораorявляетсяtruthy объектом, то общим результатом логического выражения являетсяTrue, независимо от значения правого операнда

  • если левый операнд оператораandявляетсяfalsy объектом, то общим результатом логического выражения являетсяFalse, независимо от значения правого операнда

Данный механизм называется вычислением покороткой схеме(short-circuit evaluation) и используется интерпретатором для оптимизации вычислений. Рассмотрим наглядный пример, демонстрирующий данное поведение.

Приведенный ниже код:

def f(): print('bee') return 3 if True or f(): print('geek')

выводит:

geek

Левым операндом оператора orявляетсяtruthy объект (значение True), значит, для вычисления общего результата логического выражения нет необходимости вычислять правый операнд, то есть вызывать функцию f(). Поскольку вызова функции не происходит, в выводе отсутствует строка bee. Общим результатом логического выражения является значение True, а значит, выполняются инструкции блока кода условного оператора, и в выводе мы видим строку geek.

Напротив, приведенный ниже код:

def f(): print('bee') return 3 if True and f(): print('geek')

выводит:

beegeek

Левым операндом оператора andявляетсяtruthy объект (значение True), значит, для вычисления общего результата логического выражения необходимо вычислить и правый операнд, то есть вызвать функцию f(). В результате вызова выполняются инструкции из тела функции, поэтому в выводе мы видим строку bee. Функция возвращает число 3, которое также является truthy объектом. Таким образом, общим результатом логического выражения является число 3, а значит, выполняются инструкции блока кода условного оператора, и в выводе мы видим строку geek.

Приоритет логических операторов

Важно помнить о приоритете логических операторов. Ниже логические операторы представлены в порядке уменьшения приоритета (сверху вниз):

  1. not

  2. and

  3. or

Согласно приоритету логических операторов приведенный ниже код:

a = 0b = 7c = 10print(not a and b or not c) # 7

эквивалентен следующему:

a = 0b = 7c = 10print(((not a) and b) or (not c)) # 7

По отношению к другим операторам Python (за исключением оператора присваивания =) логические операторы имеют самый низкий приоритет.

Например, приведенный ниже код:

a = 5b = 7print(not a == b) # True

эквивалентен следующему:

a = 5b = 7print(not (a == b)) # True

Отметим, что запись вида:

a = 5b = 7print(a == not b)

недопустима и приводит к возбуждению исключения SyntaxError.

Для большей наглядности рассмотрим подробно другой пример.

Приведенный ниже код:

print(not 1 == 2 or 3 == 3 and 5 == 6) 

выводит:

True

Согласно приоритету операторов в первую очередь вычисляются выражения 1 == 2, 3 == 3 и 5 == 6, в результате чего исходное выражение принимает вид not False or True and False. Далее выполняется оператор not, возвращая значение True, после него — оператор and, возвращая значение False. Выражение принимает вид True or False. Последним выполняется оператор or, возвращая общий результат выражения — значение True.

Цепочки сравнений

Иногда нам требуется объединить операции сравнения вцепочку сравнений.

Рассмотрим программный код:

a = 5b = 10c = 15print(a < b < c) # True print(a < b and b < c) # True

Выраженияa < b < cиa < b and b < cпредставляют собой сокращенный и расширенный варианты записи цепочки сравнений и являются эквивалентными, так как на самом деле дляобъединения сравнений в сокращенном выраженииa < b < cоператорandиспользуетсянеявно.

Поскольку операторandреализует вычисление покороткой схеме, все сравнения, которые располагаются правее сравнения, вернувшего ложный результат, не выполняются, и их операнды не вычисляются.

Приведенный ниже код:

def f(): print('bee') return 3if 5 < 1 < f(): print('geek')else: print('beegeek')

выводит:

beegeek

В примере выше выражение 5 < 1 < f() эквивалентно выражению 5 < 1 and 1 < f(). Сравнение5 < 1возвращаетFalse. В результате сравнение1 < f()не выполняется, и функцияf()не вызывается.

Тем не менее между сокращенным и расширенным вариантами записи цепочек сравнений существует важное отличие.

Приведенный ниже код:

def f(): print('bee') return 3if 1 < f() < 5: print('geek')

выводит:

beegeek

в то время как приведенный ниже код:

def f(): print('bee') return 3if 1 < f() and f() < 5: print('geek')

выводит:

beebeegeek

Как мы видим, в сокращенном выражении1 < f() < 5функцияf()вызывается только один раз, а в расширенном выражении1 < f() and f() < 5— два раза. Данную особенность важно учитывать, когда операнд, участвующий в сравнении, возвращает непостоянный результат.

Например, приведенный ниже код:

from random import randintdef f(): x = randint(1, 7) print(x) return xprint(1 < f() < 5)print(1 < f() and f() < 5)

выводит (результат может отличаться):

4True75False

В примере выше в сокращенной записи функцияf()вызывается один раз и возвращает значение4. Однако в расширенной записифункцияf()вызывается дважды, возвращая разные значения (7и5).Поэтому в данном случае выражения1 < f() < 5и1 < f() and f() < 5не являются эквивалентными.

Помимо операторов сравнения, в цепочку операторов могут объединяться и другие операторы Python. При этом в некоторых случаях мы можем столкнуться с неожиданным поведением программы из-за аналогичного неявного вызова оператора and.

Например, приведенный ниже код:

lst = [1, 2, 3]num = 2print(num in lst == True)

выводит:

False

Можно подумать, что результатом выражения num in lst == True должно быть значение True, однако это не так. Дело в том, что данное выражение на самом деле эквивалентно выражению num in lst and lst == True, которое, в свою очередь, эквивалентно выражению True and False. Следовательно, результатом данной цепочки операторов является значение False.

Рассмотрим еще два примера с неожиданным поведением.

Приведенный ниже код:

a = 5b = 5c = 10print(a < c is True) print(a == b in [True])

эквивалентен коду:

a = 5b = 5c = 10print(a < c and c is True)print(a == b and b in [True])

и выводит:

FalseFalse

Подведем итоги

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

Логические операторыandиorявляются ленивыми операторами. Они возвращают один из своих операндов, реализуя вычисления по короткой схеме. В цепочках операторов операторandможет использоваться неявно. Об этом всегда стоит помнить при объединении различных операторов в одно выражение.

Присоединяйтесь к нашемутелеграм-каналу, будет интересно и познавательно!

❤️ Happy Pythoning! 🐍

Секреты логических операторов в Python (2024)
Top Articles
Dagelijkse hooikoortsradar: deze pollen zitten nu in de lucht
The Atlanta Constitution from Atlanta, Georgia
Printable Whoville Houses Clipart
Mountain Dew Bennington Pontoon
Visitor Information | Medical Center
Summit County Juvenile Court
Recent Obituaries Patriot Ledger
Craigslist Kennewick Pasco Richland
Beds From Rent-A-Center
Craigslist In Fredericksburg
Skip The Games Norfolk Virginia
United Dual Complete Providers
Cars For Sale Tampa Fl Craigslist
Gina's Pizza Port Charlotte Fl
Full Range 10 Bar Selection Box
Michaels W2 Online
Radio Aleluya Dialogo Pastoral
Espn Horse Racing Results
24 Hour Drive Thru Car Wash Near Me
Christina Steele And Nathaniel Hadley Novel
Tyrone Unblocked Games Bitlife
Kaitlyn Katsaros Forum
Panolian Batesville Ms Obituaries 2022
Ontdek Pearson support voor digitaal testen en scoren
Boise Craigslist Cars And Trucks - By Owner
Anonib Oviedo
Idle Skilling Ascension
Craigslist Pasco Kennewick Richland Washington
Jesus Calling Feb 13
Pioneer Library Overdrive
Ancestors The Humankind Odyssey Wikia
Learn4Good Job Posting
Gr86 Forums
Craigslist Greencastle
Eleceed Mangaowl
Craigslist Gigs Wichita Ks
The TBM 930 Is Another Daher Masterpiece
Rs3 Bis Perks
What Is A K 56 Pink Pill?
Craigslist Boats Dallas
California Craigslist Cars For Sale By Owner
How Much Is 10000 Nickels
St Vrain Schoology
Jammiah Broomfield Ig
Devotion Showtimes Near Showplace Icon At Valley Fair
Shiftselect Carolinas
Msatlantathickdream
Diccionario De Los Sueños Misabueso
Myhrkohls.con
211475039
Bellin Employee Portal
Dr Seuss Star Bellied Sneetches Pdf
Latest Posts
Article information

Author: Annamae Dooley

Last Updated:

Views: 5955

Rating: 4.4 / 5 (45 voted)

Reviews: 92% of readers found this page helpful

Author information

Name: Annamae Dooley

Birthday: 2001-07-26

Address: 9687 Tambra Meadow, Bradleyhaven, TN 53219

Phone: +9316045904039

Job: Future Coordinator

Hobby: Archery, Couponing, Poi, Kite flying, Knitting, Rappelling, Baseball

Introduction: My name is Annamae Dooley, I am a witty, quaint, lovely, clever, rich, sparkling, powerful person who loves writing and wants to share my knowledge and understanding with you.