Каково различие между “b” и “идентификатором (a) == идентификатор (b)” в Python?

id() встроенная функция дает...

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

is оператор, вместо этого, дает...

объектные идентификационные данные

Итак, почему возможно иметь два объекта, которые имеют то же id но возвратитесь False к is проверить? Вот пример:

>>> class Test():
...   def test():
...     pass
>>> a = Test()
>>> b = Test()
>>> id(a.test) == id(b.test)
True
>>> a.test is b.test
False

Больше беспокоящегося примера: (продолжающееся вышеупомянутое)

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

Однако:

>>> new_improved_test_method = lambda: None
>>> a.test = new_improved_test_method
>>> a.test is a.test
True

34
задан badp 25 May 2010 в 15:48
поделиться

1 ответ

>>> b.test is a.test
False
>>> a.test is a.test
False

Методы создаются "на лету" каждый раз, когда вы их просматриваете. Функциональный объект (который всегда является одним и тем же объектом) реализует протокол дескриптора , а его __ get __ создает связанный объект метода. Обычно два связанных метода не могут быть одним и тем же объектом.

>>> id(a.test) == id(b.test)
True
>>> a.test is b.test
False

Этот пример обманчив. Результат первого только Истинный по совпадению. a.test создает связанный метод и собирает мусор после вычисления id (a.test) , потому что на него нет никаких ссылок. (Обратите внимание, что вы цитируете документацию, в которой говорится, что идентификатор является «уникальным и постоянным для этого объекта в течение его жизни » (выделено мной).) b.test бывает , чтобы иметь тот же идентификатор, что и у связанного метода, который у вас был раньше, и это разрешено, потому что сейчас у других объектов нет такого же идентификатора.

Обратите внимание, что вы должны редко использовать is и еще реже использовать id . id (foo) == id (bar) всегда неверен.


Что касается вашего нового примера, надеюсь, вы теперь понимаете, что он делает:

>>> new_improved_test_method = lambda: None
>>> a.test = new_improved_test_method
>>> a.test is a.test
True

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

57
ответ дан 27 November 2019 в 16:53
поделиться
Другие вопросы по тегам:

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