I was playing around a bit with polymorphism and super()
in python classes with inheritance and found that I didn't understand the following behavior.
In this dummy example, I found that I can access the instance variables and class variables for the child class, and class variable for the parent class, directly from the object of the child class, BUT I was unsuccessful in accessing the instance variable for the parent class.
I understand that I would have to create an object of the parent class using super()
but am unable to access the instance variables from parent class. I don't want to explicitly return anything in the parent.__init__()
.
The only way I found to do this is to explicitly create an object of the parent class and then fetch the required variable, but that hinders proper abstraction of the code.
Is there a way I can access parent_object._color
after its constructor is run, using super()
, without explicit instantiation of the parent class object?
#parent class
class hat:
_color = 'red' #Parent class variable
def __init__(self):
self._color = 'yellow' #Parent object variable
#child class
class cap(hat):
_color = 'green' #Child class variable
def __init__(self, color): #Child instance variable (passed)
self._color = color
@property
def parent_color_super(self):
return super()._color #super() only gives access to class variables
@property
def parent_color_explicit(self):
return hat()._color #explicit object constructor allows access to instance variable
c = cap('blue')
print(c._color) #Attribute lookup: Instance variable
print(c.__class__._color) #Attribute lookup: class variable
print(c.__class__.__bases__[0]._color) #Attribute lookup: parent class variable
print(c.parent_color_super) #<---
print(c.parent_color_explicit) #<---
blue
green
red
red #<--- how to get this as yellow!
yellow #<---
EDIT 2:
Based on the valuable answers from @Silvio Mayolo, @user2357112, and @Mad Physicist, I think I understand where the issue was.
As I understand, the child class's instance c
will hold the instance variable _color
which will get overwritten by the super().__init__()
as the job of that function is to update the self._color
of whichever object its called from.
This means, as clarified by the answers, there is no separate "parent instance variables" that can be accessed by super()
; only class attributes such as the class variable _color
(red) and __init__()
(which sets the instance variable _color
to (yellow).
A modified example to show this behavior is as follows -
class hat:
_color = 'red' #Parent class variable
def __init__(self): #Sets instance variable to yellow
self._color = 'yellow'
class cap(hat):
_color = 'green' #Child class variable
def __init__(self, color): #Child instance variable (passed)
self._color = color
def parent_color_super(self): #Call __init__ from parent, overwrites _color
super().__init__()
c = cap('blue')
print(c._color) #Attribute lookup: Instance variable
print(c.__class__._color) #Attribute lookup: class variable
print(c.__class__.__bases__[0]._color) #Attribute lookup: parent class variable
c.parent_color_super() #Call init from super class
print(c._color) #Attribute lookup: Updated Instance variable
blue
green
red
yellow