Использование равенства строк равно [duplicate]

Благодаря @tleyden в swagger-ui / issues для хороших подсказок!

Используйте папку index и assets этого проекта, https: // github.com/okfn-brasil/swagger-ui-html

926
задан BuZZ-dEE 20 November 2015 в 14:28
поделиться

14 ответов

Это побочная заметка, но в идиоматическом питоне вы часто увидите такие вещи, как:

if x is None: 
    # some clauses

Это безопасно, потому что гарантированно будет один экземпляр объекта Null (т. е. None) .

1235
ответ дан SilentGhost 22 August 2018 в 10:14
поделиться
  • 1
    ahh же, как eq? vs равно? в схеме, получил его. – jottos 1 October 2009 в 18:00
  • 2
    В Common Lisp существует много предикатов равенства, помимо базовой иерархии eq, eql, equal и equalp (чем дольше будет имя, тем больше будет найдено одинаковое). – David Thornley 1 October 2009 в 20:43
  • 3
    Или == vs .equals() в Java. Наилучшая часть состоит в том, что Python == не похож на Java ==. – MatrixFrog 4 February 2012 в 04:48
  • 4
    @ Крайст: существует только одно значение None. Таким образом, он всегда имеет один и тот же идентификатор. – SilentGhost 29 October 2012 в 11:57
  • 5
    Это не относится к OP's is is - & gt; Правда & Quot; пример. – user2864740 10 September 2014 в 05:53
  • 6
    Я обдумывал это. вдруг я увидел ваш ответ! – Juggernaut 19 January 2017 в 16:44
  • 7
    То же самое верно для True и False? Будет только один экземпляр? – HandyManDan 1 June 2018 в 18:00
1276
ответ дан SilentGhost 5 November 2018 в 07:29
поделиться

is - тестирование идентичности, == - тестирование равенства (см. Документация Python ).

В большинстве случаев, если a is b, то a == b. Но есть исключения, например:

>>> nan = float('nan')
>>> nan is nan
True
>>> nan == nan
False

Таким образом, вы можете использовать is для тестирования идентичности, никогда не проводить тесты равенства.

1
ответ дан Christian König 22 August 2018 в 10:14
поделиться

Другие ответы здесь верны: is используется для сравнения identity , а == используется для сравнения равенство . Поскольку вам нужно заботиться о равенстве (две строки должны содержать одни и те же символы), в этом случае оператор is просто ошибочен, и вы должны использовать вместо него ==.

Причина is работает интерактивно, что (большинство) строковых литералов по умолчанию interned . Из Wikipedia:

Интернированные строки ускоряют сопоставления строк, которые иногда являются узким местом производительности в приложениях (например, компиляторами и языками динамического программирования), которые в значительной степени зависят от хэш-таблиц со строковыми ключами. Без интернирования проверка того, что две разные строки равны, включает в себя изучение каждого символа обеих строк. Это медленно по нескольким причинам: по своей сути это O (n) в длине строк; обычно требуется чтение из нескольких областей памяти, которые требуют времени; и чтение считывает кеш процессора, что означает, что для других нужд меньше кеша. С интернированными строками после первоначальной статической операции достаточно простого теста на идентификацию объекта; это обычно реализуется как тест равенства указателя, обычно это всего лишь одна машинная команда без ссылки на память.

Итак, когда у вас есть два строковых литерала (слова, которые буквально введены в ваш исходный код программы, окруженный кавычками) в вашей программе, имеющей то же значение, компилятор Python автоматически ставит строки, делая их оба сохраненными в том же месте памяти. (Обратите внимание, что это не всегда всегда , а правила для того, когда это происходит, довольно запутаны, поэтому, пожалуйста, не полагайтесь на это поведение в производственном коде!) [/ ​​G12]

Поскольку в вашем интерактивном сеансе обе строки фактически хранятся в одном и том же месте памяти, у них одинаковое identity , поэтому оператор is работает так, как ожидалось. Но если вы построите строку другим способом (даже если эта строка содержит точно одинаковые символы), то строка может быть равна , но это не одна и та же строка , то есть она имеет другое тождество , поскольку оно хранится в другом месте в памяти.

442
ответ дан Daniel Pryden 22 August 2018 в 10:14
поделиться
  • 1
    Где кто-то может прочитать больше о запутанных правилах, когда строки интернированы? – Noctis Skytower 11 April 2013 в 15:14
  • 2
    +1 для подробного объяснения. Не уверен, как в другом ответе было так много упреков, не объяснив, что НАСТОЯТЕЛЬНО произошло. – That1Guy 29 April 2013 в 03:07
  • 3
    это именно то, о чем я думал, когда я читал вопрос. Принятый ответ короткий, но содержит факт, но этот ответ объясняет вещи намного лучше. Ницца! – Sнаđошƒаӽ 19 July 2015 в 05:46
  • 4
    @NoctisSkytower Googled то же самое и нашел это guilload.com/python-string-interning – xtreak 10 March 2016 в 15:41
  • 5
    @ naught101: Нет, правило состоит в том, чтобы выбрать между == и is в зависимости от того, какую проверку вы хотите. Если вам нужны строки equal (то есть, имеющие одинаковое содержимое), вы всегда должны использовать ==. Если вам небезразлично, ссылаются ли какие-либо два имени Python на один и тот же экземпляр объекта, вы должны использовать is. Возможно, вам понадобится is, если вы пишете код, который обрабатывает множество разных значений, не заботясь об их содержимом, иначе, если вы знаете, что есть только один из них, и вы хотите игнорировать другие объекты, претендующие на то, что они есть. Если вы не уверены, всегда выбирайте ==. – Daniel Pryden 18 October 2016 в 19:30

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

Вот хороший пример:

>>> s1 = u'public'
>>> s2 = 'public'
>>> s1 is s2
False
>>> s1 == s2
True

s1 - строка в Юникоде, а s2 - обычная строка. Они не одного типа, но имеют одинаковое значение.

16
ответ дан Jack M. 22 August 2018 в 10:14
поделиться
  • 1
    Ваш пример по-прежнему следует за старым текстом .... – jprete 2 October 2009 в 17:16

В последнее время вы можете использовать функцию intern, чтобы убедиться, что вы получаете ссылку на одну и ту же строку:

>>> a = intern('a')
>>> a2 = intern('a')
>>> a is a2
True

Как указано выше, вы, вероятно, не должны делать является определение равенства по строкам. Но это может быть полезно узнать, есть ли у вас какое-то странное требование использовать is.

Обратите внимание, что функция-интернатура перешла из встроенной функции в модуль sys для Python 3.

48
ответ дан Jason Baker 22 August 2018 в 10:14
поделиться

is сравнивает местоположение памяти. Он используется для сравнения уровня объекта.

== будет сравнивать переменные в программе. Он используется для проверки на уровне ценности.

is проверяет эквивалентность уровня адреса

== проверяет эквивалентность уровня значения

0
ответ дан johnashu 22 August 2018 в 10:14
поделиться

Если вы не уверены, что делаете, используйте '=='. Если у вас есть немного больше знаний об этом, вы можете использовать «is» для известных объектов, таких как «None».

В противном случае вы будете удивлены, почему все не работает и почему это происходит:

>>> a = 1
>>> b = 1
>>> b is a
True
>>> a = 6000
>>> b = 6000
>>> b is a
False

Я даже не уверен, что некоторые вещи гарантированно останутся неизменными между различными версиями / реализациями python.

23
ответ дан Mattias Nilsson 22 August 2018 в 10:14
поделиться
  • 1
    Интересный пример показывает, как переназначение int делает триггеры этим условием. Почему это не удалось? Это связано с интернированием или чем-то еще? – Paul 22 December 2014 в 17:49
  • 2
    Похоже, причина, по которой возвращает false, может быть вызвана реализацией интерпретатора: stackoverflow.com/questions/132988/… – Paul 22 December 2014 в 17:55
  • 3
  • 4
    @ArchitJain Да, эти ссылки объясняют это довольно хорошо. Когда вы их прочтете, вы узнаете, какие цифры вы можете использовать «есть». Я просто хочу, чтобы они объяснили, почему это еще не очень хорошая идея. Знаете ли вы, что это не значит, что предположить, что все остальное тоже (или что интернализованный диапазон номеров никогда не изменится) – Mattias Nilsson 29 December 2015 в 14:32

Я думаю, что это связано с тем, что, когда сравнение «is» оценивается как false, используются два разных объекта. Если он оценивает значение true, это означает, что внутри он использует один и тот же точный объект, а не создает новый, возможно, потому, что вы создали их за долю в 2 или около того секунд и потому, что между ним нет большого промежутка времени и использует тот же объект.

Вот почему вы должны использовать оператор равенства ==, а не is, чтобы сравнить значение строкового объекта.

>>> s = 'one'
>>> s2 = 'two'
>>> s is s2
False
>>> s2 = s2.replace('two', 'one')
>>> s2
'one'
>>> s2 is s
False
>>> 

В этом примере я сделал s2, который был другим строковым объектом, ранее равным «одному», но это не тот же объект, что и s, потому что интерпретатор не использовал тот же объект, что и я, один ', если бы я сделал это, это сделало бы их одним и тем же объектом.

12
ответ дан meder omuraliev 22 August 2018 в 10:14
поделиться
  • 1
    Использование .replace() в качестве примера в этом контексте, вероятно, не самое лучшее, хотя, поскольку его семантика может сбить с толку. s2 = s2.replace() будет всегда создавать строковый объект new , назначить новый строковый объект на s2, а затем удалить строковый объект, который s2 использовал для указания на , Поэтому, даже если вы s = s.replace('one', 'one'), вы все равно получите новый строковый объект. – Daniel Pryden 1 October 2009 в 17:20
  • 2
    Ах, хорошая точка, и это правда. – meder omuraliev 1 October 2009 в 17:46

is - тестирование идентичности, == - проверка равенства. Это означает, что is - это способ проверить, являются ли две вещи одинаковыми вещами или просто эквивалентны.

Скажем, у вас есть простой объект person. Если он называется «Джек» и ему «23 года», он эквивалентен другому 23-летнему Джеку, но его не одному человеку.

class Person(object):
   def __init__(self, name, age):
       self.name = name
       self.age = age

   def __eq__(self, other):
       return self.name == other.name and self.age == other.age

jack1 = Person('Jack', 23)
jack2 = Person('Jack', 23)

jack1 == jack2 #True
jack1 is jack2 #False

Они того же возраста, не один и тот же экземпляр человека. Строка может быть эквивалентна другой, но это не тот же объект.

30
ответ дан Morgan Thrapp 22 August 2018 в 10:14
поделиться

Я отвечаю на вопрос, даже если вопрос старен, потому что ни один из ответов выше не цитирует ссылку на язык

На самом деле оператор проверяет идентификаторы и == проверяет оператор на равенство,

Из справочника по языку:

Типы затрагивают почти все аспекты поведения объекта. Даже значение идентичности объектов в некотором смысле влияет: для неизменяемых типов операции, которые вычисляют новые значения, могут фактически возвращать ссылку на любой существующий объект с тем же типом и значением, в то время как для изменяемых объектов это недопустимо. Например, после a = 1; b = 1, a и b могут или не могут ссылаться на один и тот же объект со значением один, в зависимости от реализации, но после c = []; d = [], c и d гарантированно относятся к двум различным уникальным, вновь созданным пустым спискам. (Обратите внимание, что c = d = [] присваивает один и тот же объект как c, так и d.)

, поэтому из вышеприведенного утверждения мы можем заключить, что строки, которые являются неизменяемым, могут сбой при проверке с помощью «is» и может проверяться успешно, если отмечено с помощью «is»

То же самое относится к int, кортежу, которые также являются неизменяемыми типами

9
ответ дан Ram 22 August 2018 в 10:14
поделиться

Ключевое слово is - это тест для идентификации объекта, а == - сравнение значений.

Если вы используете is, результат будет истинным тогда и только тогда, когда объект является тот же объект. Однако == будет истинным в любое время, когда значения объекта будут одинаковыми.

94
ответ дан Thomas Owens 22 August 2018 в 10:14
поделиться

Эквивалентность тестового значения оператора ==. Оператор is проверяет идентичность объекта, Python проверяет, действительно ли эти два являются одним и тем же объектом (т. Е. Живут по одному и тому же адресу в памяти).

>>> a = 'banana'
>>> b = 'banana'
>>> a is b 
True

В этом примере Python создал только одну строку объект, и оба a и b ссылаются на него. Причина в том, что Python внутренне кэширует и использует несколько строк в качестве оптимизации, на самом деле в памяти есть только строка «банан», разделяемая a и b; Чтобы вызвать нормальное поведение, вам нужно использовать более длинные строки:

>>> a = 'a longer banana'
>>> b = 'a longer banana'
>>> a == b, a is b
(True, False)

Когда вы создаете два списка, вы получаете два объекта:

>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> a is b
False

В этом случае мы сказали бы: что эти два списка эквивалентны, потому что они имеют одинаковые элементы, но не идентичны, потому что они не являются одним и тем же объектом. Если два объекта идентичны, они также эквивалентны, но если они эквивалентны, они не обязательно идентичны.

Если a ссылается на объект и вы назначаете b = a, то обе переменные ссылаются на тот же объект:

>>> a = [1, 2, 3]
>>> b = a
>>> b is a
True
3
ответ дан X. Wang 22 August 2018 в 10:14
поделиться

Я считаю, что это известно как «интернированные» строки. Python делает это, так же как и Java, а также C и C ++ при компиляции в оптимизированных режимах.

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

Это приводит к тому, что оператор Python «is» возвращает True, потому что две строки с тем же содержимым указывают на один и тот же строковый объект. Это также произойдет в Java и в C.

Это полезно только для экономии памяти. Вы не можете полагаться на него, чтобы проверить равенство строк, потому что различные интерпретаторы, компиляторы и JIT-механизмы не всегда могут это сделать.

11
ответ дан Zan Lynx 22 August 2018 в 10:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: