這是CPython 2.7.2和3.2.2。爲什麼一些引用``x.y``的表達式改變``id(x.y)``?
假設我們定義如下Class
和obj
。
class Class(object):
def m(self):
pass
@property
def p(self):
return None
@staticmethod
def s():
pass
obj = Class()
短版
爲什麼每個print()
下面的代碼輸出False
?
print(Class.__dict__ is Class.__dict__)
print(Class.__subclasshook__ is Class.__subclasshook__)
print(Class.m is Class.m)
print(obj.__delattr__ is obj.__delattr__)
print(obj.__format__ is obj.__format__)
print(obj.__getattribute__ is obj.__getattribute__)
print(obj.__hash__ is obj.__hash__)
print(obj.__init__ is obj.__init__)
print(obj.__reduce__ is obj.__reduce__)
print(obj.__reduce_ex__ is obj.__reduce_ex__)
print(obj.__repr__ is obj.__repr__)
print(obj.__setattr__ is obj.__setattr__)
print(obj.__sizeof__ is obj.__sizeof__)
print(obj.__str__ is obj.__str__)
print(obj.__subclasshook__ is obj.__subclasshook__)
print(obj.m is obj.m)
(這是在Python 2;對於Python 3中,省略了print()
爲Class.m
並添加類似於那些爲obj.__eq__
,obj.__ge__
,obj.__gt__
,obj.__le__
,obj.__lt__
和obj.__ne__
)
,爲什麼,相比之下,以下代碼是否爲print()
輸出True
?
print(Class.__class__ is Class.__class__)
print(Class.__delattr__ is Class.__delattr__)
print(Class.__doc__ is Class.__doc__)
print(Class.__format__ is Class.__format__)
print(Class.__getattribute__ is Class.__getattribute__)
print(Class.__hash__ is Class.__hash__)
print(Class.__init__ is Class.__init__)
print(Class.__module__ is Class.__module__)
print(Class.__new__ is Class.__new__)
print(Class.__reduce__ is Class.__reduce__)
print(Class.__reduce_ex__ is Class.__reduce_ex__)
print(Class.__repr__ is Class.__repr__)
print(Class.__setattr__ is Class.__setattr__)
print(Class.__sizeof__ is Class.__sizeof__)
print(Class.__str__ is Class.__str__)
print(Class.__weakref__ is Class.__weakref__)
print(Class.p is Class.p)
print(Class.s is Class.s)
print(obj.__class__ is obj.__class__)
print(obj.__dict__ is obj.__dict__)
print(obj.__doc__ is obj.__doc__)
print(obj.__module__ is obj.__module__)
print(obj.__new__ is obj.__new__)
print(obj.__weakref__ is obj.__weakref__)
print(obj.p is obj.p)
print(obj.s is obj.s)
(這是在Python 2;爲Python 3,對於Class.__eq__
,Class.__ge__
,Class.__gt__
,Class.__le__
,Class.__lt__
和Class.__ne__
添加類似於print()
秒,Class.m
)
長版
如果我們連續詢問id(obj.m)
兩次,然後我們得到相同的ID兩次。
>>> id(obj.m)
139675714789856
>>> id(obj.m)
139675714789856
但如果我們要求id(obj.m)
,然後一些表達式包含對obj.m
,然後再id(obj.m)
,該ID的變化有時(但不總是)。如果它改變了,那麼如果我們再次要求id(obj.m)
,則ID有時(但並非總是)變回原始值。如果它沒有變回,那麼看起來重複中間表達式會導致ID在兩個值之間交替。
這裏是一些例子,其中id(obj.m)
不會改變:
>>> print(obj.m); id(obj.m)
<bound method Class.m of <__main__.Class object at 0x7f08c96058d0>>
139675714789856
>>> obj.m is None; id(obj.m)
False
139675714789856
>>> obj.m.__func__.__name__; id(obj.m)
'm'
139675714789856
>>> obj.m(); id(obj.m)
139675714789856
這裏是一個例子,其中id(obj.m)
變更,然後變回:
>>> obj.m; id(obj.m); id(obj.m)
<bound method Class.m of <__main__.Class object at 0x7f08c96058d0>>
139675715407536
139675714789856
這裏是一個例子,其中id(obj.m)
變化,然後不改回:
>>> obj.m is obj.m; id(obj.m); id(obj.m)
False
139675715407536
139675715407536
這裏是同樣的表情,反覆幾次後證明交替行爲:
>>> obj.m is obj.m; id(obj.m); id(obj.m)
False
139675714789856
139675714789856
>>> obj.m is obj.m; id(obj.m); id(obj.m)
False
139675715407536
139675715407536
>>> obj.m is obj.m; id(obj.m); id(obj.m)
False
139675714789856
139675714789856
因此我的整個問題是
- 什麼樣的屬性,可能會改變他們的身份表達的副作用那些不會修改這些屬性?
- 什麼樣的表達式觸發這樣的改變?
- 導致這種變化的機制是什麼?
- 在什麼條件下回收過去的身份?
- 爲什麼不是無限循環的第一個身份,這將避免所有這些併發症?
- 是否有任何記錄?
@ kindall的回答解決了我的大部分問題,但是這解決了有關回收ID的子問題。謝謝。 – nisavid 2013-05-21 16:35:00