Reputation: 151
class BaseA(object):
authors = ['a', 'b']
author_list = authors
class BaseB(object):
authors = ['a', 'b']
def __init__(self, *arg, **kwargs):
self.author_list = self.authors
class ChildA(BaseA):
authors = ['c', 'd']
class ChildB(BaseB):
authors = ['c', 'd']
child_a = ChildA()
child_b = ChildB()
print(child_a.author_list)
print(child_b.author_list)
>>> ['a', 'b']
>>> ['c', 'd']
What's the different of the codes? Why do I get different results?
I'm so confusing why parent author_list attributes don't be override.
Can you tell me the principle of python inheritance?
Upvotes: 1
Views: 220
Reputation: 373
class BaseA(object):
def __init__(self):
self.authors = ['a', 'b']
class BaseB(object):
def __init__(self):
self.authors = ['a', 'b']
class ChildA(BaseA):
def __init__(self):
self.authors = ['c', 'd']
class ChildB(BaseB):
def __init__(self):
self.authors = ['c', 'd']
child_a = ChildA()
child_b = ChildB()
print(child_a.authors)
print(child_b.authors)
>>> ['c', 'd']
>>> ['c', 'd']
class BaseA(object):
def __init__(self):
self.authors = ['a', 'b']
class BaseB(object):
def __init__(self):
self.authors = ['a', 'b']
class ChildA(BaseA):
def __init__(self):
self.authors = ['c', 'd']
super().__init__()
class ChildB(BaseB):
def __init__(self):
self.authors = ['c', 'd']
BaseB.__init__(self)
child_a = ChildA()
child_b = ChildB()
print(child_a.authors)
print(child_b.authors)
>>> ['a', 'b']
>>> ['a', 'b']
__init__ (__init_)
:class BaseA(object):
def __init__(self):
self.authors = ['a', 'b']
class BaseB(object):
def __init__(self):
self.authors = ['a', 'b']
class ChildA(BaseA):
def __init_(self):
self.authors = ['c', 'd']
class ChildB(BaseB):
def __init_(self):
self.authors = ['c', 'd']
child_a = ChildA()
child_b = ChildB()
print(child_a.authors)
print(child_b.authors)
>>> ['a', 'b']
>>> ['a', 'b']
Access to methods in the subclass (Child class) will still be accessible, but all access to variables in the subclass (Child class) will be lost completely.
Upvotes: 0
Reputation: 373
In your BaseB __init__
function you are calling the Child's authors, not the Parent's authors.
If you wish to call the Parent's authors you would use BaseB.authors
instead of self.authors
:
class BaseA(object):
authors = ['a', 'b']
author_list = authors
class BaseB(object):
authors = ['a', 'b']
def __init__(self, *arg, **kwargs):
self.author_list = BaseB.authors
class ChildA(BaseA):
authors = ['c', 'd']
class ChildB(BaseB):
authors = ['c', 'd']
child_a = ChildA()
child_b = ChildB()
print(child_a.author_list)
print(child_b.author_list)
>>> ['a', 'b']
>>> ['a', 'b']
In the case where you would be concatenating the authors of the ParentB and the ChildB then you would use both BaseB.authors
and self.authors
:
class BaseA(object):
authors = ['a', 'b']
author_list = authors
class BaseB(object):
authors = ['a', 'b']
def __init__(self, *arg, **kwargs):
self.author_list = BaseB.authors + self.authors
class ChildA(BaseA):
authors = ['c', 'd']
class ChildB(BaseB):
authors = ['c', 'd']
child_a = ChildA()
child_b = ChildB()
print(child_a.author_list)
print(child_b.author_list)
>>> ['a', 'b']
>>> ['a', 'b', 'c', 'd']
class BaseA(object):
authors = ['a', 'b']
author_list = authors
class BaseB(object):
authors = ['a', 'b']
def __init__(self, *arg, **kwargs):
self.author_list = self.authors
class ChildA(BaseA):
authors = ['c', 'd']
def __init__(self, *arg, **kwargs):
self.author_list = self.authors
class ChildB(BaseB):
authors = ['c', 'd']
child_a = ChildA()
child_b = ChildB()
print(child_a.author_list)
print(child_b.author_list)
>>> ['c', 'd']
>>> ['c', 'd']
Upvotes: 0
Reputation: 251558
Material inside the class
block is part of the class itself, and is executed once, when you define the class. Material in __init__
is per-instance, and is executed once per instance, every time you instantiate the class.
In your first example (BaseA
), you create a class attribute authors
, then create another attribute author_list
pointing to the same value. That is it. Nothing else ever happens. The fact that ChildA
inherits from BaseA
does not cause author_list = authors
to be re-executed. author_list
was over and done with once BaseA
was defined.
In your second example (BaseB
), you create a class attribute authors
. Then in __init__
you make a new instance attribute pointing at that same value. Since you do this in __init__
, it is re-done for each instance. So when you instantiate BaseB
, it gets the new attribute.
Note that you are checking the attributes on the instances child_a
and child_b
. If you check them on the classes (ChildA.author_list
and ChildB.author_list
), you will see that both have the same value (['a', 'b']
). Because your action in ChildB takes place in __init__
, it only takes effect when you actually instantiate the class.
Upvotes: 4
Reputation: 3107
The difference is that in the second example, author_list
is set when you create an instance of an object.
When you define class BaseA
you define the class member author_list
and that's that, so when you create an instance of ChildA
nothing is happening to author_list
. It is just inherited.
When you define BaseB
there is no member author_list
. That is created as a instance variable when an instance of BaseB
is created. So, when you create an instance of ChildB
the same thing happens, but since authors
is redefined then it will use the new value of authors
Upvotes: 0