почему выражение __name__ is '__main__' оценивает True в debug, но False во время выполнения? [Дубликат]

Основываясь на нескольких предложениях на разных форумах и экспериментируя со стандартной библиотекой, чтобы соответствовать критериям, мой текущий вывод заключается в том, что это невозможно сделать с библиотекой и типами, которые у нас в настоящее время есть.

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

13 ответов

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

if x is None: 
    # some clauses

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

1235
ответ дан SilentGhost 23 August 2018 в 23:08
поделиться

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

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

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

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

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

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

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

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

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

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

442
ответ дан Daniel Pryden 23 August 2018 в 23:08
поделиться

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

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

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

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

16
ответ дан Jack M. 23 August 2018 в 23:08
поделиться

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

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

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

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

48
ответ дан Jason Baker 23 August 2018 в 23:08
поделиться

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

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

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

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

0
ответ дан johnashu 23 August 2018 в 23:08
поделиться

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

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

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

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

23
ответ дан Mattias Nilsson 23 August 2018 в 23:08
поделиться

Я думаю, что это связано с тем, что, когда сравнение «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 23 August 2018 в 23:08
поделиться

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 23 August 2018 в 23:08
поделиться

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

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

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

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

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

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

9
ответ дан Ram 23 August 2018 в 23:08
поделиться

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

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

94
ответ дан Thomas Owens 23 August 2018 в 23:08
поделиться

Эквивалентность тестового значения оператора ==. Оператор 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 23 August 2018 в 23:08
поделиться

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

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

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

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

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

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