То, почему делает, "является" ключевым словом, имеют другое поведение, когда существует точка в строке?

Рассмотрите этот код:

>>> x = "google"
>>> x is "google"
True
>>> x = "google.com"
>>> x is "google.com"
False
>>>

Почему похож на это это?

Для проверки вышеупомянутое корректно, я только что протестировал на Python 2.5.4, 2.6.5, 2.7b2, Python 3.1 на окнах и Python 2.7b1 на Linux.

Похоже, что существует непротиворечивость через всех них, таким образом, это дизайном. Я пропускаю что-то?

Я просто нахожу его этим из части моего персонального сценария доменной фильтрации, переставшего работать с этим.

56
задан Peter Mortensen 22 November 2014 в 15:00
поделиться

2 ответа

is проверяет идентичность объекта, и любая реализация Python, когда она встречает литерал неизменяемых типов, совершенно бесплатна для либо создания нового объекта этого неизменяемого type, или просматривают существующие объекты этого типа, чтобы увидеть, можно ли использовать некоторые из них повторно (путем добавления новой ссылки на тот же базовый объект).Это прагматичный выбор оптимизации и не подвержен семантическим ограничениям, поэтому ваш код никогда не должен полагаться на то, какой путь может выбрать реализация give (или он может сломаться с исправлением ошибок / выпуском оптимизации Python!).

Рассмотрим, например:

>>> import dis
>>> def f():
...   x = 'google.com'
...   return x is 'google.com'
... 
>>> dis.dis(f)
  2           0 LOAD_CONST               1 ('google.com')
              3 STORE_FAST               0 (x)

  3           6 LOAD_FAST                0 (x)
              9 LOAD_CONST               1 ('google.com')
             12 COMPARE_OP               8 (is)
             15 RETURN_VALUE    

, поэтому в этой конкретной реализации, в функции , ваше наблюдение не применяется, и только один объект создается для литерала (любого литерала), и действительно:

>>> f()
True

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

Но та же самая реализация, в интерактивной подсказке ( Edit : изначально я думал, что это также произойдет на верхнем уровне модуля, но комментарий @Thomas заставил меня справа, см. ниже):

>>> x = 'google.com'
>>> y = 'google.com'
>>> id(x), id(y)
(4213000, 4290864)

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

Редактировать : на верхнем уровне модуля, согласно наблюдениям @Thomas, например, например:

$ cat aaa.py
x = 'google.com'
y = 'google.com'
print id(x), id(y)

, мы снова видим оптимизацию памяти на основе таблиц констант в этой реализации:

>>> import aaa
4291104 4291104

(конец Edit за наблюдение @Thomas).

Наконец, снова в той же реализации:

>>> x = 'google'
>>> y = 'google'
>>> id(x), id(y)
(2484672, 2484672)

эвристика здесь другая, потому что буквальная строка «выглядит так, будто это может быть идентификатор» - поэтому ее можно использовать в операции, требующей интернирования ... поэтому оптимизатор стажируется в любом случае (и после интернирования поиск, конечно, становится очень быстрым). И действительно, сюрприз-сюрприз ...:

>>> z = intern(x)
>>> id(z)
2484672

... x был стажером в первый раз (как вы видите, возвращаемое значение ] intern - это тот же объект , что и x и y , поскольку он имеет тот же id () ). Конечно, вы тоже не должны полагаться на это - оптимизатор не имеет для автоматического интернирования чего-либо, это просто эвристика оптимизации; если вам нужна intern ed строка, intern их явно, на всякий случай. Когда вы явно выполняете внутренние строки ...:

>>> x = intern('google.com')
>>> y = intern('google.com')
>>> id(x), id(y)
(4213000, 4213000)

... тогда вы делаете точно такой же объект (то есть тот же id () ) результаты каждый раз - так что вы можете применять микрооптимизации, такие как проверка с помощью , это , а не == (я вряд ли когда-либо обнаружил, что незначительный прирост производительности стоит того беспокоить;-).

Правка : просто для пояснения, вот какие различия в производительности, о которых я говорю, на медленном Macbook Air ...:

$ python -mtimeit -s"a='google';b='google'" 'a==b'
10000000 loops, best of 3: 0.132 usec per loop
$ python -mtimeit -s"a='google';b='google'" 'a is b'
10000000 loops, best of 3: 0.107 usec per loop
$ python -mtimeit -s"a='goo.gle';b='goo.gle'" 'a==b'
10000000 loops, best of 3: 0.132 usec per loop
$ python -mtimeit -s"a='google';b='google'" 'a is b'
10000000 loops, best of 3: 0.106 usec per loop
$ python -mtimeit -s"a=intern('goo.gle');b=intern('goo.gle')" 'a is b'
10000000 loops, best of 3: 0.0966 usec per loop
$ python -mtimeit -s"a=intern('goo.gle');b=intern('goo.gle')" 'a == b'
10000000 loops, best of 3: 0.126 usec per loop

... несколько десятков наносекунд в любом случае, самое большее .Так что даже стоит думать только о самых крайних «оптимизациях [ругательства удалено] из этого [ругательства удалено] узкого места в производительности»! -)

90
ответ дан 26 November 2019 в 17:21
поделиться

«is» - это проверка личности. Python имеет некоторое поведение кеширования для небольших целых чисел и (очевидно) строк. «is» лучше всего использовать для одноэлементного тестирования (например, None ).

>>> x = "google"
>>> x is "google"
True
>>> id(x)
32553984L
>>> id("google")
32553984L
>>> x = "google.com"
>>> x is "google.com"
False
>>> id(x)
32649320L
>>> id("google.com")
37787888L
15
ответ дан 26 November 2019 в 17:21
поделиться
Другие вопросы по тегам:

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