I write the test code with 3 classes , and using Chain of Responsibility design pattern , the code below
and I print print(c._abc is b._abc)
, the answer is True , but my original think is that the two are different.
Then , Round 2 , I uncomment self._abc = kwargs
and comment other 3 lines ,
the answer become False .
Why is it so?
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()
Inheritance allows us to define a class that inherits all the methods and properties from another class. Parent class is the class being inherited from, also called base class. Child class is the class that inherits from another class, also called derived class.
You need to explicitly call the constructor. It isn't called for you automatically like in C++ Use a new-style class inherited from object. With a new-style class, use the super() method available.
Two built-in functions isinstance() and issubclass() are used to check inheritances. The function isinstance() returns True if the object is an instance of the class or other classes derived from it. Each and every class in Python inherits from the base class object .
First just to make it clear I would like to state that _abc
is a class variable, not an instance variable so its address space is shared across parent and child class. Any change in the original _abc
object affects all the class's _abc
object. Read about class and instance variable (here at SO and here at DO)
To check that _abc
share the same address space we can use python built-in id():
id() Return the “identity” of an object. This is an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.
To check this in the first round we can do:
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
All of them gives the same value for id(). In round 2, when you uncomment self._abc = kwargs
see what happens to the value of 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
Value of b._abc gets changed but the value of c._abc and A._abc remains the same. So, what is actually happening here?
When in round 1 you do:
# self._abc = kwargs
self._abc['a'] = kwargs['a']
self._abc['b'] = kwargs['b']
self._abc['Hello'] = 'World'
You are actually modifying the shared class variable _abc
. Your code here is not creating a new self._abc
object it is modifying the original self._abc
class variable object but in round 2 when you do:
self._abc = kwargs
Here, the code is assigning kwargs
, which is a dictionary with its own address space, to self._abc
. self._abc
becomes class B's instance variable and it is only available to the class B's objects.
To verify this point you can modify your class B to print id's as:
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
As you can see originally self._abc had address 4585627152
and kwargs had 4583538904
but after self._abc= kwargs
self._abc
's new id is 4583538904.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With