Інший дублікат запитував, чому два рівних рядки взагалі не однакові, на що насправді тут не відповіли:
>>> x = 'a'
>>> x += 'bc'
>>> y = 'abc'
>>> x == y
True
>>> x is y
False
Отже, чому вони не є однією строкою? Особливо враховуючи це:
>>> z = 'abc'
>>> w = 'abc'
>>> z is w
True
Давайте трохи відкладемо другу частину. Як перша може бути правдою?
Інтерпретатор повинен мати "таблицю інтернування", таблицю зіставленням рядкових значень для рядкових об'єктів, тому кожен раз, коли ви намагаєтесь створити нову рядок із вмістом 'abc'
, ви отримуєте назад той самий об'єкт. У Вікіпедії є більш детальне обговорення того, як працює стажування.
І у Python є стіл для інтернування; ви можете вручну інтернувати рядки sys.intern
методом.
Насправді Python дозволено автоматично стажувати будь-які незмінні типи, але цього не вимагає . У різних реалізаціях будуть інтернуватися різні значення.
CPython (реалізація, яку ви використовуєте, якщо ви не знаєте, яку саме програму ви використовуєте) автоматично інтернірує невеликі цілі числа та деякі спеціальні сингтони, такі як False
, але не рядки (або великі цілі числа, або маленькі кортежі, або щось інше). Ви можете це легко побачити:
>>> a = 0
>>> a += 1
>>> b = 1
>>> a is b
True
>>> a = False
>>> a = not a
>>> b = True
a is b
True
>>> a = 1000
>>> a += 1
>>> b = 1001
>>> a is b
False
Гаразд, але чому були z
і w
однакові?
Це не інтерпретатор, який автоматично стажується, це значення компілятора.
Якщо ж у час компіляції рядок з'являється двічі в одному модулі (що саме це означає, важко визначити, що це не те ж саме , як строковий літерал, тому що r'abc'
, 'abc'
і 'a' 'b' 'c'
всі різні літерали , але та ж рядок, але легко зрозуміти , інтуїтивно) компілятор створить лише один екземпляр рядка з двома посиланнями.
Насправді компілятор може піти ще далі: 'ab' + 'c'
може бути перетворений 'abc'
оптимізатором, і в цьому випадку він може бути складений разом із 'abc'
константою в одному модулі.
Знову ж таки, це Python дозволено, але цього не потрібно робити. Але в цьому випадку CPython завжди складається з невеликих рядків (а також, наприклад, маленьких кортежів). .
Отже, що ви повинні зробити з цим як програміст?
Ну ... нічого. Ви майже ніколи не маєте підстав піклуватися про те, чи є дві незмінні значення однакові. Якщо ви хочете знати, коли ви можете використовувати a is b
замість цього a == b
, ви задаєте неправильне запитання. Просто завжди використовуйте, a == b
за винятком двох випадків:
- Для більш зрозумілого порівняння значень одиночного типу
x is None
.
- Щодо змінних значень, коли вам потрібно знати, чи
x
вплине мутація на y
.