2010-05-25 5 views
29

id() встроенная функция дает ...В чем разница между «a is b» и «id (a) == id (b)» в Python?

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

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 
+0

Это не похоже на то, что я сделал это для реальной программы или метаклассического трюка джедая, заметьте. Мне было скучно в поезде, и я пробовал это :) – badp

+0

Я думаю, что важным вопросом является то, почему 'a.test является a.test' является False. Как только вы узнаете, что остальное должно иметь смысл ... – Skilldrick

+0

Нефть разлива прекрасна и денди, и она приближается к городу рядом с вами.Может быть, вы должны организовать встречу, чтобы отпраздновать свое пришествие! – badp

ответ

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

методы создаются на лету каждого время, когда вы их просматриваете. Объект функции (который всегда является одним и тем же объектом) реализует descriptor protocol, а его __get__ создает объект связанного метода. Нет двух связанных методов, как правило, одного и того же объекта.

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

Этот пример обманчив. Результатом первого является только True по совпадению. a.test создает связанный метод, и это мусор, собранный после вычисления id(a.test), потому что ссылок на него нет. (Обратите внимание, что вы цитируете документацию о том, что id является «уникальным и постоянным для этого объекта в течение его жизни» (выделение мое).) 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 

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

+3

Очень хорошо! .. ... – Skilldrick

+7

* «Методы создаются« на лету »каждый раз, когда вы их просматриваете. Объект функции (который всегда является одним и тем же объектом) реализует протокол дескриптора, а его' __get__' создает объект связанного метода. методы, как правило, являются одним и тем же объектом ». Ха, это новость для меня. Ницца! –

+1

Вау, очень поучительный, спасибо! – PaulMcG

Смежные вопросы