Чи є різниця між ==і isв Python?
Так, вони мають дуже важливу різницю.
==: перевірка рівності - семантика полягає в тому, що еквівалентні об'єкти (які необов'язково є одним і тим же об'єктом) перевірятимуться як рівні. Як зазначено в документації :
Оператори <,>, ==,> =, <= і! = Порівнюють значення двох об'єктів.
is: перевірка на ідентичність - семантика полягає в тому, що об'єкт (як зберігається в пам'яті) є об'єктом. Знову ж таки, документація говорить :
Оператори isі is notтест на ідентичність об'єкта: x is yістинно, якщо і лише тоді, коли xі yє тим самим об'єктом. Ідентифікація об'єкта визначається за допомогою id()функції. x is not yдає зворотне значення істини.
Таким чином, перевірка на ідентичність - це те саме, що перевірка рівності ідентифікаторів об'єктів. Це є,
a is b
те саме, що:
id(a) == id(b)
де idвбудована функція, яка повертає ціле число, яке "гарантовано буде унікальним серед одночасно існуючих об'єктів" (див. help(id)), а де aі bє будь-які довільні об'єкти.
Інші вказівки щодо використання
Ви повинні використовувати ці порівняння для їх семантики. Використовуйте isдля перевірки ідентичності та ==для перевірки рівності.
Тож загалом ми використовуємо isдля перевірки особи. Зазвичай це корисно, коли ми перевіряємо наявність об'єкта, який повинен існувати лише один раз у пам'яті, який у документації позначається як "синглтон".
Випадки isвикористання:
None
- значення enum (при використанні Enums з модуля enum)
- зазвичай модулі
- зазвичай об'єкти класу, що є результатом визначень класів
- зазвичай функціонують об'єкти, що є результатом визначень функцій
- все інше, що повинно існувати лише один раз у пам'яті (всі одиночні кнопки, як правило)
- конкретний об'єкт, який ви хочете за особою
Звичайні випадки використання для ==включають:
- числа, включаючи цілі числа
- струни
- списки
- набори
- словники
- спеціальні об'єкти, що змінюються
- інші вбудовані незмінні об'єкти, в більшості випадків
Загальний випадок використання, знову ж , для ==, це об'єкт , який ви хочете , не може бути той же об'єкт, а це може бути еквівалентно один
PEP 8 напрямків
PEP 8, офіційний посібник зі стилів Python для стандартної бібліотеки, також згадує два випадки використання дляis :
Порівняння з одинаковими, як Noneі завжди, слід проводити з операторами рівності isабо
is not, ніколи.
Крім того, остерігайтеся писати, if xколи ви дійсно маєте на увазі if x is not None- наприклад, під час тестування, чи змінна або аргумент, для якого за замовчуванням None
було встановлено якесь інше значення. Інше значення може мати тип (наприклад, контейнер), який може бути помилковим у булевому контексті!
Визначення рівності від ідентичності
Якщо isце правда, зазвичай можна зробити висновок про рівність - логічно, якщо об'єкт є самим собою, то він повинен перевірятися як рівноцінний собі.
У більшості випадків ця логіка є вірною, але вона спирається на реалізацію __eq__спеціального методу. Як кажуть документи ,
Поведінка за замовчуванням для порівняння ( ==та !=) рівності базується на ідентичності об'єктів. Отже, порівняння рівності випадків з однаковою ідентичністю призводить до рівності, а порівняння рівності випадків з різними тотожностями призводить до нерівності. Мотивацією такої поведінки за замовчуванням є бажання, щоб усі об'єкти були рефлексивними (тобто x є y означає x == y).
і в інтересах послідовності рекомендує:
Порівняння рівності повинно бути рефлексивним. Іншими словами, ідентичні об'єкти повинні порівнювати:
x is y мається на увазі x == y
Ми можемо побачити, що це поведінка за замовчуванням для користувацьких об'єктів:
>>> class Object(object): pass
>>> obj = Object()
>>> obj2 = Object()
>>> obj == obj, obj is obj
(True, True)
>>> obj == obj2, obj is obj2
(False, False)
Протипоказання також зазвичай справедливо - якщо тест чогось не є рівним, зазвичай можна зробити висновок, що вони не є одним і тим же об'єктом.
Оскільки тести на рівність можна налаштувати, цей висновок не завжди відповідає дійсності для всіх типів.
Виняток
Помітним винятком є те, що nanвін завжди перевіряється як не рівний собі:
>>> nan = float('nan')
>>> nan
nan
>>> nan is nan
True
>>> nan == nan # !!!!!
False
Перевірка ідентичності може бути набагато швидшою, ніж перевірка рівності (що може вимагати рекурсивної перевірки членів).
Але це не може бути замінено рівністю, коли ви можете знайти більш ніж один об'єкт як еквівалент.
Зауважте, що порівняння рівності списків та кортежів передбачає, що ідентичність об'єктів однакова (адже це швидка перевірка). Це може створити суперечності, якщо логіка суперечлива - як для nan:
>>> [nan] == [nan]
True
>>> (nan,) == (nan,)
True
Попереджувальна казка:
Питання намагається використовувати isдля порівняння цілих чисел. Не слід вважати, що екземпляр цілого числа є тим самим екземпляром, що і інший, отриманий іншою посиланням. Ця історія пояснює, чому.
Коментер мав код, який спирався на те, що малі цілі числа (від -5 до 256 включно) є одинаковими в Python, замість перевірки рівності.
Ого, це може призвести до деяких підступних помилок. У мене був якийсь код, який перевіряв, якщо a є b, який працював так, як я хотів, тому що a і b, як правило, невеликі числа. Помилка трапилася лише сьогодні, через півроку виробництва, тому що a і b нарешті були досить великими, щоб їх не було кешовано. - gwg
Це працювало в розвитку. Можливо, пройшли деякі тести.
І він працював у виробництві - доки код не перевірив ціле число, що перевищує 256, і в цей момент він не вдався у виробництві.
Це збій у виробництві, який міг потрапити в перегляд коду або, можливо, за допомогою перевірки стилів.
Дозвольте підкреслити: не використовуйте isдля порівняння цілих чисел.
echo 'import sys;tt=sys.argv[1];print(tt is "foo", tt == "foo", id(tt)==id("foo"))'| python3 - foooutput :False True False.