[英]Python - Confused about inheritance
我用3個類編寫測試代碼,並使用Chain of Responsibility設計模式,下面的代碼
我打印print(c._abc is b._abc)
,答案是真的,但我原來認為這兩者是不同的。
然后,第2輪,我取消注釋self._abc = kwargs
並評論其他3行,答案變為False。
為什么會這樣?
import abc
class A:
__metaclass__ = abc.ABCMeta
_abc = {}
def __init__(self,successor=None,**kwargs):
self._successor = successor
@abc.abstractmethod
def handlerRequest(self):
pass
class B(A):
def __init__(self,successor=None,**kwargs):
self._successor = successor
print(kwargs)
# self._abc = kwargs # round 2<---uncomment here
self._abc['a'] = kwargs['a'] # round 2<---comment here
self._abc['b'] = kwargs['b'] # round 2<---comment here
self._abc['Hello'] = 'World' # round 2<---comment here
def handlerRequest(self):
if (self._successor is not None):
self._successor.handlerRequest()
print(self._abc)
class C(A):
def handlerRequest(self):
if (self._successor is not None):
self._successor.handlerRequest()
print(self._abc)
list = {'a':1,'b':2}
b = B(**list)
c = C(b)
print(c._abc is b._abc)
c.handlerRequest()
首先只是為了說清楚我想聲明_abc
是一個類變量,而不是一個實例變量,因此它的地址空間在父類和子類之間共享。 原始 _abc
對象中的任何更改都會影響所有類的_abc
對象。 閱讀有關類和實例變量的內容( 此處為SO , 此處為DO )
要檢查_abc
共享相同的地址空間,我們可以使用python內置的id() :
id()返回對象的“標識”。 這是一個整數(或長整數),保證在該生命周期內該對象是唯一且恆定的。 具有非重疊生存期的兩個對象可以具有相同的id()值。
要在第一輪中檢查這一點,我們可以:
In [33]: id(c._abc)
Out[33]: 4454841440
In [34]: id(b._abc)
Out[34]: 4454841440
In [36]: id(A._abc)
Out[36]: 4454841440
In [38]: id(B._abc)
Out[38]: 4454841440
In [39]: id(C._abc)
Out[39]: 4454841440
所有這些都為id()提供了相同的值。 在第2輪中,當你取消注釋self._abc = kwargs
看看id()的值會發生什么:
In [8]: id(b._abc)
Out[8]: 4585625712 # its different from A._abc and c._abc why?
In [9]: id(c._abc)
Out[9]: 4585627152 # same as A._abc
In [10]: id(A._abc)
Out[10]: 4585627152 # this is same as c._abc
b._abc的值會發生變化,但c._abc和A._abc的值保持不變。 那么,這里到底發生了什么?
在第1輪你做的時候:
# self._abc = kwargs
self._abc['a'] = kwargs['a']
self._abc['b'] = kwargs['b']
self._abc['Hello'] = 'World'
您實際上正在修改共享類變量_abc
。 你的代碼在這里沒有創建一個新的self._abc
對象,它正在修改原始的self._abc
類變量對象,但在第2輪中你做了:
self._abc = kwargs
這里,代碼將自 self._abc
kwargs
( 具有自己的地址空間的字典 )分配給self._abc
。 self._abc
成為B類的實例變量,它只能用於B類的對象。
要驗證這一點,您可以修改B類以打印ID為:
In [11]: class B(A):
...:
...: def __init__(self,successor=None,**kwargs):
...: self._successor = successor
...: print(id(self._abc))
...: print(id(kwargs))
...: self._abc = kwargs
...: print(id(self._abc))
In [12]: b = B(**list)
4585627152 # original self._abc id
4583538904 # kwargs object's id
4583538904 # New self._abc id
正如你可以看到原來有self._abc地址4585627152
和kwargs不得不4583538904
但經過self._abc= kwargs
self._abc
的新的ID是4583538904。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.