Порівняння цінностей
Оновлено: 24.04.2023
Оператори <, >, ==, >=, <= і != порівнюють значення двох об’єктів. Об’єкти не обов’язково мають однаковий тип.
У розділі Об’єкти, значення та типи зазначено, що об’єкти мають значення (крім типу та ідентичності). Значення об’єкта є досить абстрактним поняттям у Python: наприклад, не існує канонічного методу доступу до значення об’єкта. Крім того, немає вимоги, щоб значення об’єкта було сконструйовано певним чином, напр. складається з усіх своїх атрибутів даних. Оператори порівняння реалізують певне уявлення про цінність об’єкта. Можна думати про них як про визначення значення об’єкта опосередковано, за допомогою реалізації порівняння.
Оскільки всі типи є (прямими чи непрямими) підтипами object, вони успадковують типову поведінку порівняння від object. Типи можуть налаштувати свою поведінку порівняння, реалізувавши багаті методи порівняння, такі як __lt__(), описані в Базове налаштування.
Поведінка за умовчанням для порівняння рівності (== і !=) базується на ідентичності об’єктів. Отже, порівняння рівності екземплярів з однаковою тотожністю призводить до рівності, а порівняння рівності екземплярів з різними ідентичністями призводить до нерівності. Мотивацією такої поведінки за замовчуванням є бажання, щоб усі об’єкти були рефлексивними (тобто x є y означає x == y).
Порівняння порядку за замовчуванням (<, >, <=, and > =) не надається; спроба викликає TypeError. Мотивацією такої поведінки за замовчуванням є відсутність аналогічного інваріанта, як для рівності.
Поведінка порівняння рівності за замовчуванням, тобто екземпляри з різними ідентифікаторами завжди нерівні, може відрізнятися від того, які типи потребуватимуть розумного визначення значення об’єкта та рівності на основі значення. Таким типам потрібно буде налаштувати свою поведінку порівняння, і насправді це зробили кілька вбудованих типів.
У наведеному нижче списку описано поведінку порівняння найважливіших вбудованих типів.
Числа вбудованих числових типів (Числові типи — int, float, complex) і стандартних бібліотечних типів fractions.Fraction і decimal.Decimal можна порівнювати всередині та між типами, з обмеженням що комплексні числа не підтримують порівняння порядку. У межах залучених типів вони порівнюють математично (алгоритмічно) правильно без втрати точності. Нечислові значення float('NaN') і decimal.Decimal('NaN') є спеціальними. Будь-яке впорядковане порівняння числа з нечисловим значенням є хибним. Протиінтуїтивний висновок полягає в тому, що нечислові значення не дорівнюють самі собі. Наприклад, якщо x = float('NaN'), 3 < x, x < 3 і x == x є помилковими, тоді як x ! = x вірно. Така поведінка відповідає стандарту IEEE 754. None і NotImplemented є одиночними елементами. PEP 8 радить, що порівняння одиночних елементів завжди слід виконувати за допомогою is або is not, а не операторів рівності. Двійкові послідовності (екземпляри bytes або bytearray) можна порівнювати всередині та між типами. Вони порівнюють лексикографічно, використовуючи числові значення своїх елементів. Рядки (примірники str) порівнюються лексикографічно за допомогою числових кодових точок Unicode (результат вбудованої функції ord()) їхніх символів. 3 Рядки та двійкові послідовності не можна безпосередньо порівнювати. Послідовності (екземпляри tuple, list або range) можна порівнювати лише в межах кожного зі своїх типів, з обмеженням, що діапазони не підтримують порівняння порядку. Порівняння рівності між цими типами призводить до нерівності, а впорядковане порівняння між цими типами викликає TypeError. Послідовності порівнюють лексикографічно за допомогою порівняння відповідних елементів. Вбудовані контейнери зазвичай припускають, що ідентичні об’єкти рівні самі собі. Це дозволяє їм обійти тести на рівність для ідентичних об’єктів, щоб підвищити продуктивність і зберегти свої внутрішні інваріанти. Лексикографічне порівняння між вбудованими колекціями працює таким чином: Щоб дві колекції порівнювалися однаково, вони повинні бути одного типу, мати однакову довжину, і кожна пара відповідних елементів має порівнюватися однаковими (наприклад, [1,2] == (1,2) false, оскільки тип не той самий). Колекції, які підтримують порівняння порядку, упорядковуються так само, як і їхні перші нерівні елементи (наприклад, [1,2,x] <= [1,2,y] має те саме значення, що x <= y). Якщо відповідний елемент не існує, коротша колекція впорядковується першою (наприклад, [1,2] < [1,2,3] є істинним). Mappings (instances of dict) compare equal if and only if they have equal (key, value) pairs. Equality comparison of the keys and values enforces reflexivity. Порівняння порядку (<, >, <=, and > =) викликає TypeError. Набори (екземпляри set або frozenset) можна порівнювати всередині та між типами. Вони визначають оператори порівняння порядку, щоб означати тести підмножини та надмножини. Ці відносини не визначають загальних порядків (наприклад, дві множини {1,2} і {2,3} не є рівними, ані підмножини одна одної, ані надмножини одна одної). Відповідно, набори не є відповідними аргументами для функцій, які залежать від загального порядку (наприклад, min(), max() і sorted() дають невизначені результати, якщо ввести список наборів як вхідні дані) . Порівняння множин посилює рефлексивність її елементів. Більшість інших вбудованих типів не мають реалізованих методів порівняння, тому вони успадковують типову поведінку порівняння.
Визначені користувачем класи, які налаштовують свою поведінку порівняння, повинні дотримуватися деяких правил узгодженості, якщо це можливо:
Порівняння рівності має бути рефлексивним. Іншими словами, ідентичні об’єкти повинні порівнюватися рівними: x є y означає x == y Порівняння має бути симетричним. Іншими словами, наступні вирази повинні мати однаковий результат: x == y і y == x x != y і y != x x < y and y > x x <= y and y > = x Порівняння має бути транзитивним. Наступні (невичерпні) приклади ілюструють це: x > y і y > z передбачає x > z x < y і y <= z передбачає x < z Зворотне порівняння має призвести до логічного заперечення. Іншими словами, наступні вирази повинні мати однаковий результат: x == y і не x != y x < y and not x > = y (для загального впорядкування) x > y і not x <= y (для загального порядку) Останні два вирази застосовуються до повністю впорядкованих колекцій (наприклад, до послідовностей, але не до наборів чи відображень). Дивіться також декоратор total_ordering(). Результат hash() має відповідати рівності. Рівні об’єкти повинні або мати однакове хеш-значення, або бути позначеними як нехешовані.
Python не забезпечує виконання цих правил узгодженості. Фактично, нечислові значення є прикладом недотримання цих правил.