Python підтримує такі базові оператори порівняння:
| Оператор | Операція | Опис |
|---|---|---|
> |
«більше ніж» |
a > b дорівнює True, якщо a строго більше за b за значенням |
< |
«менше ніж» |
a < b дорівнює True, якщо a строго менше за b за значенням |
== |
«дорівнює» |
a == b дорівнює True, якщо a строго дорівнює b за значенням |
>= |
«більше ніж або дорівнює» |
a >= b дорівнює True, якщо a > b АБО a == b за значенням |
<= |
«менше ніж або дорівнює» |
a <= b дорівнює True, якщо a < b або a == b за значенням |
!= |
«не дорівнює» |
a != b дорівнює True, якщо a == b дорівнює False
|
is |
«ідентичність» |
a is b дорівнює True, якщо і тільки якщо a і b є тим самим обʼєктом
|
is not |
«заперечення ідентичності» |
a is not b дорівнює True, якщо a і b не є тим самим обʼєктом
|
in |
«перевірка входження» |
a in b дорівнює True, якщо a є членом, підмножиною або елементом b
|
not in |
«заперечення перевірки входження» |
a not in b дорівнює True, якщо a не є членом, підмножиною або елементом b
|
Усі вони мають однаковий пріоритет (вищий, ніж у булевих операцій (англ. Boolean), але нижчий, ніж в арифметичних чи побітових операцій).
Обʼєкти різних типів (крім числових типів) типово ніколи не вважаються рівними.
Неідентичні примірники class також не вважатимуться рівними, якщо тільки class не визначає спеціальних методів розширеного порівняння, які змінюють типову поведінку порівняння object.
Налаштування через rich comparisons розглянемо в одній із наступних вправ.
Щоб дізнатися (набагато) більше про цю тему, дивіться порівняння значень у документації Python.
Числові типи (переважно) є винятком із цього правила відповідності типів.
integer може вважатися рівним float (або octal рівним hexadecimal), якщо типи можна неявно перетворити для порівняння.
Для інших числових типів зі стандартної бібліотеки Python (complex, decimal, fractions) оператори порівняння визначено там, де вони «мають сенс» (де неявне перетворення не змінює результат), але вони викликають TypeError, якщо базові обʼєкти не можна точно перетворити для порівняння.
Докладніше про правила, які Python використовує для числового перетворення, дивіться в розділі арифметичні перетворення у документації Python.
>>> import fractions
# A string cannot be converted to an int.
>>> 17 == '17'
False
# An int can be converted to float for comparison.
>>> 17 == 17.0
True
# The fraction 6/3 can be converted to the int 2
# The int 2 can be converted to 0b10 in binary.
>>> 6/3 == 0b10
True
# An int can be converted to a complex number with a 0 imaginary part.
>>> 17 == complex(17)
True
# The fraction 2/5 can be converted to the float 0.4
>>> 0.4 == 2/5
True
>>> complex(2/5, 1/2) == complex(0.4, 0.5)
True
Будь-яке впорядковане порівняння числа з типом NaN (не число) дає False.
Заплутаний побічний ефект визначення NaN у Python полягає в тому, що NaN ніколи не вважається рівним NaN.
>>> x = float('NaN')
>>> 3 < x
False
>>> x < 3
False
# NaN never compares equal to NaN
>>> x == x
False
На відміну від чисел, рядки тексту (англ. string) (str) порівнюються лексикографічно, за їхніми окремими кодовими точками Unicode (результат передачі кожної кодової точки зі str у вбудовану функцію ord(), яка повертає int).
Якщо всі кодові точки в обох рядках тексту збігаються і розташовані в однаковому порядку, ці два рядки тексту вважаються рівними.
Це порівняння виконується попарно: перший з першим, другий з другим тощо.
У Python 3.x str і bytes не можна безпосередньо звести одне до одного чи порівняти.
>>> 'Python' > 'Rust'
False
>>> 'Python' > 'JavaScript'
True
# Examples with Mandarin.
# hello < goodbye
>>> '你好' < '再见'
True
# ord() of first characters
>>> ord('你'), ord('再')
(20320, 20877)
# ord() of second characters
>>> ord('好'), ord('见')
(22909, 35265)
# And with Korean words.
# Pretty < beautiful.
>>> '예쁜' < '아름다운'
False
>>> ord('예'), ord('아')
(50696, 50500)
Оператори порівняння можна обʼєднувати в ланцюжки довільно, тобто використовувати в будь-якій комбінації будь-якої довжини.
Зауважмо, що обчислення виразу відбувається від left до right.
Наприклад, x < y <= z еквівалентний x < y and y <= z, за винятком того, що y обчислюється лише один раз.
В обох випадках z не обчислюється взагалі, коли x < y виявляється False.
Це часто називають short-circuit evaluation: обчислення припиняється, якщо істинність виразу вже встановлено.
Short circuiting підтримують різні булеві оператори, функції, а також ланцюгове порівняння в Python.
На відміну від багатьох інших мов програмування, зокрема C, C++, C# і Java, ланцюгові вирази на кшталт a < b < c у Python мають звичне математичне тлумачення і пріоритет.
>>> x = 2
>>> y = 5
>>> z = 10
>>> x < y < z
True
>>> x < y > z
False
>>> x > y < z
False
Оператори is і is not перевіряють ідентичність обʼєкта, а не його значення.
Ідентичність обʼєкта ніколи не змінюється після створення, і її можна дізнатися за допомогою функції id().
<apple> is <orange> дає True, якщо і тільки якщо id(<apple>) == id(<orange>).
<apple> is not <orange> дає протилежний результат.
Через те, що None і NotImplemented є єдиними у своєму роді, для їх порівняння з іншими обʼєктами завжди варто використовувати is і is not.
Докладніше про цю конвенцію дивіться в довідці Python про порівняння значень і в PEP8.
>>> my_fav_numbers = [1, 2, 3]
>>> your_fav_numbers = my_fav_numbers
>>> my_fav_numbers is your_fav_numbers
True
# The returned id will differ by system and python version.
>>> id(my_fav_numbers)
4517478208
# your_fav_numbers is only an alias pointing to the original my_fav_numbers object.
# Assigning a new name does not create a new object.
>>> id(your_fav_numbers)
4517478208
>>> my_fav_numbers is not your_fav_numbers
False
>>> my_fav_numbers is not None
True
>>> my_fav_numbers is NotImplemented
False
Оператори in і not in перевіряють належність.
<fish> in <soup> дає True, якщо <fish> є членом <soup> (якщо <fish> є підмножиною <soup> або міститься в ньому), а інакше дає False.
<fish> not in <soup> повертає заперечення, тобто протилежне до <fish> in <soup>.
Для типів рядків тексту і bytes вираз <name> in <fullname> дорівнює True і тільки якщо <name> є підрядком <fullname>.
# A set of lucky numbers.
>>> lucky_numbers = {11, 22, 33}
>>> 22 in lucky_numbers
True
>>> 44 in lucky_numbers
False
# A dictionary of employee information.
>>> employee = {'name': 'John Doe',
'id': 67826, 'age': 33,
'title': 'ceo'}
# Checking for the membership of certain keys.
>>> 'age' in employee
True
>>> 33 in employee
False
>>> 'lastname' not in employee
True
# Checking for substring membership
>>> name = 'Super Batman'
>>> 'Bat' in name
True
>>> 'Batwoman' in name
False
У цій вправі ми реалізуємо деякі правила блекджеку, зокрема те, як у неї грають і нараховують очки.
Примітка: у цій вправі A означає туза, J — валета, Q — даму, а K означає короля.
Джокерів відкидають.
Мається на увазі стандартна колода з 52 карт французьких мастей, але в більшості версій для гри перемішують кілька колод разом.
У блекджеку кожен гравець сам вирішує, чи туз коштує 1 чи 11 очок (про це далі).
Фігурні карти (J, Q, K) дають 10 очок, а будь-яка інша карта коштує свій «номінал» (числове значення).
Визначте функцію value_of_card(<card>) з параметром card.
Функція повинна повертати числове значення переданої карти у вигляді рядка тексту (англ. string).
Оскільки туз може мати кілька значень (1 або 11), поки що ця функція має фіксувати значення туза на 1.
Пізніше ми реалізуємо функцію, щоб визначати значення туза з урахуванням наявної руки.
>>> value_of_card('K')
10
>>> value_of_card('4')
4
>>> value_of_card('A')
1
Визначте функцію higher_card(<card_one>, <card_two>) з параметрами card_one і card_two.
Для нарахування очок значення J, Q чи K дорівнює 10.
Функція повинна повертати карту з вищим значенням для нарахування очок.
Якщо обидві карти мають однакове значення, поверніть обидві.
Повернути обидві карти можна, використавши кому в інструкції return:
# Using a comma in a return creates a Tuple. Tuples will be covered in a later exercise.
>>> def returning_two_values(value_one, value_two):
return value_one, value_two
>>> returning_two_values('K', '3')
('K', '3')
Туз може мати кілька значень, тож у цьому завданні ми зафіксуємо значення карт A на 1.
>>> higher_card('K', '10')
('K', '10')
>>> higher_card('4', '6')
'6'
>>> higher_card('K', 'A')
'K'
Як уже згадувалося, туз може коштувати або 1, або 11 очок. Гравці намагаються якомога ближче підійти до 21 очка, не перевищивши 21 (не «перебравши»).
Визначте функцію value_of_ace(<card_one>, <card_two>) з параметрами card_one і card_two, які є парою карт, що вже є в руці перед отриманням туза.
Функція має вирішити, чи туз, який надійде, отримає значення 1 чи 11, і повернути це значення.
Памʼятаймо: значення руки з тузом має бути якомога вищим, не перевищуючи 21.
Підказка: якщо в руці вже є туз, тоді значенням для туза, який надійде, буде 1.
>>> value_of_ace('6', 'K')
1
>>> value_of_ace('7', '3')
11
Якщо гравцеві як перші дві карти роздають туза (A) і карту вартістю десять (10, K, Q чи J), то він має 21 очко.
Таку руку називають блекджек.
Визначте функцію is_blackjack(<card_one>, <card_two>) з параметрами card_one і card_two, які є парою карт.
Визначте, чи ця рука з двох карт є блекджеком, і поверніть булеве значення (англ. Boolean) True, якщо так, і False в іншому разі.
Примітка: обчислити очки можна багатьма способами. Але якщо це можливо, хотілося б, щоб ми перевіряли наявність туза і карти вартістю десять у руці (або на певній позиції), а не сумували значення руки.
>>> is_blackjack('A', 'K')
True
>>> is_blackjack('10', '9')
False
Якщо перші дві карти в руці мають однакове значення (наприклад, дві шістки або Q і K), гравець може вирішити вважати їх двома окремими руками.
Це називають «розділенням пар».
Визначте функцію can_split_pairs(<card_one>, <card_two>) з параметрами card_one і card_two, які є парою карт.
Визначте, чи цю руку з двох карт можна розділити на дві пари.
Якщо руку можна розділити, поверніть булеве значення True, інакше поверніть False
>>> can_split_pairs('Q', 'K')
True
>>> can_split_pairs('10', 'A')
False
Коли дві початкові роздані карти дають у сумі 9, 10 або 11 очок, гравець може зробити додаткову ставку, що дорівнює початковій. Це називають «подвоєнням ставки».
Визначте функцію can_double_down(<card_one>, <card_two>) з параметрами card_one і card_two, які є парою карт.
Визначте, чи цю руку з двох карт можна «подвоїти», і поверніть булеве значення True, якщо так, і False в іншому разі.
>>> can_double_down('A', '9')
True
>>> can_double_down('10', '2')
False
Зареєструйтеся на Exercism, щоб вивчати й опановувати Python, а також 17 концепцій146 вправ та справжнє наставництво від людей, і все це безкоштовно.