Когда использовать == и когда использовать?

Любопытно:

>>> a = 123
>>> b = 123
>>> a is b
True
>>> a = 123.
>>> b = 123.
>>> a is b
False

Кажется, что a is b более или менее определен как id(a) == id(b). Легко сделать ошибки следующим образом:

basename, ext = os.path.splitext(fname)
if ext is '.mp3':
    # do something
else:
    # do something else

Некоторые псевдонимы неожиданно оказались в блоке else. Исправить это просто, мы должны использовать ext == '.mp3' вместо этого, но тем не менее if ext is '.mp3' на поверхности кажется хорошим питоновским способом написать это и более читаемым, чем "правильным" способом.

Так как строки неизменяемы, каковы технические детали того, почему это неправильно? Когда проверка подлинности лучше, а когда проверка равенства лучше?

Ответ 1

Насколько я могу судить, is проверяет эквивалентность идентификатора объекта. Поскольку нет обязательного "интернационализации строк", две строки, которые, как правило, имеют одинаковые символы в последовательности, обычно не являются одним и тем же строковым объектом.

Когда вы извлекаете подстроку из строки (или, действительно, любую подпоследовательность из последовательности), вы получите два разных объекта, содержащих одинаковые значения.

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

Ответ 2

Они принципиально разные.

  • == сравнивается, вызывая метод __eq__
  • is возвращает true тогда и только тогда, когда две ссылки относятся к одному и тому же объекту

Итак, в сравнении с Java:

  • is совпадает с == для объектов
  • == совпадает с equals для объектов

Ответ 3

Простое правило для определения, использовать или == в Python

Вот простое правило (если вы не хотите перейти к теории в интерпретаторе Python или создавать фреймворки, делающие забавные вещи с объектами Python):

Использование используется только для сравнения None.

if foo is None

В противном случае используйте ==.

if x == 3

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

Ответ 4

Было бы также полезно определить класс, подобный этому, который будет использоваться как значение по умолчанию для констант, используемых в вашем API. В этом случае было бы правильнее использовать, чем оператор ==.

class Sentinel(object):
    """A constant object that does not change even when copied."""
    def __deepcopy__(self, memo):
        # Always return the same object because this is essentially a constant.
        return self

    def __copy__(self):
        # called via copy.copy(x)
        return self

Ответ 5

PyCharm должен предупредить вас, когда вы используете is с литералом с предупреждением, таким как SyntaxWarning: "is" with a literal. Did you mean "=="?. Поэтому при сравнении с литералом всегда используйте ==. В противном случае вы можете предпочесть использовать is для сравнения объектов по их ссылкам.