Attribute inherited from child class prints child object not string from parent - python

I know many topics around class inheritance in Python have been addressed, but I could not find a thread that addressed this specific issue.
Edit: I'm running Python 3.5.5.
Code:
class Parent():
def __init__(self, parentParam="parent param"):
self.parentParam = parentParam
class Child(Parent):
def __init__(self, childParam = "child param"):
self.childParam = childParam
super().__init__(self)
child = Child()
print(child.childParam)
print(child.parentParam)
Output:
child param
<__main__.Child object at 0x0000017CE7C0CAC8>
Why does does child.parentParam return the child object and not the string "parent param"? I feel like it should print out the default string set for the Parent class. This appears to be the same syntax as I have been following in this tutorial.
Thanks, everyone.

Because you provide the instance of child (aka self) to the super call:
class Child(Parent):
def __init__(self, childParam = "child param"):
self.childParam = childParam
super().__init__(self) # here you override the default by supplying this instance
Use:
class Child(Parent):
def __init__(self, childParam = "child param"):
self.childParam = childParam
super().__init__()
instead and you get this output instead:
child param
parent param

Your call to super is wrong. It's not necessary to explicitly pass a self argument when using it to delegate a method call to a superclass (see the typical usage example shown in the documentation).
In Python 3, calls to super() with no arguments are equivalent to super(CurrentClass, self).method(arg)—which was the only way it could be done in Python 2—making it no longer necessary to specify it at all when making calls to superclass methods.
So what's happening, since you passed it in your code, is that it gets interpreted as overriding the default value specified for the parentParam argument.
Here's doing it properly and the result:
class Parent:
def __init__(self, parentParam="parent param"):
self.parentParam = parentParam
class Child(Parent):
def __init__(self, childParam="child param"):
self.childParam = childParam
super().__init__() # NO NEED TO PASS self.
child = Child()
print(child.childParam) # -> child param
print(child.parentParam) # -> parent param

Related

How Child class constructor set the parent class attribute

In python, how can I setup the Parent class attributes in Child Class constructor.
My Parent class has 2 attributes which set in its constructor:
class Parent:
def __init__(self):
self.attribute1 = "abc"
self.attribute2 = 1
def afunction():
# something to print attributes"
print(self.attribute1 + self.attribute2)
In my child class, in the construtor, I try to override the attribute1, attribute2 by
class Child(Parent):
def __init__(self):
super.attribute1 = "def"
super.attribute2 = 3
But I get error TypeError: can't set attributes of built-in/extension type 'super'
What i want to when x = Child() x.afunction(), I should see it print "def3"
You should use the inheritance right way. Your parent class already have 2 attributes, but you are not exposing them to be parametrized to be instantiated by clients as well as subclasses. You could do this as follows:
class Parent:
def __init__(self, attribute1="abc", attribute2=1):
self.attribute1 = attribute1
self.attribute2 = attribute2
def afunction(self):
print(self.attribute1 + str(self.attribute2))
class Child(Parent):
def __init__(self, attribute1="def", attribute2=3):
super().__init__(attribute1, attribute2)
Child().afunction()
Child("test", 3).afunction()
This way you are allowing clients to provide value for your attributes, not reassign them in child. Also exposing attributes to the clients so they can pass them if they need else it uses the default value
To build up on my comment:
class Parent:
def __init__(self):
self.attribute1 = "abc"
self.attribute2 = 1
class Child(Parent):
def __init__(self):
self.attribute1 = "def"
self.attribute2 = 3
c = Child()
In this case, the child is initialize. In the initialization 2 attributes are created with the value def and 3. The attributes are never initialized with the values from the parent class.
Alternatively:
class Parent:
def __init__(self):
self.attribute1 = "abc"
self.attribute2 = 1
class Child(Parent):
def __init__(self):
super().__init__()
self.attribute1 = "def"
self.attribute2 = 3
c = Child()
This time, the attributes are first initialized during the super() call by calling the function __init__() from the parent class. And then they are overridden.
Which one you prefer depends on your application, but either way, you can create the attribute directly in the child class as they don't belong to one specifically.
Got It In Place Of Super() try Acccesing It With Parent.
And Then Print It I Definitely Say You Will Get Your Answer :'def'

Call parent method inside super().__init__ when method is overriden by child

I have overriden a method in a child class.
This method is used in the parent class constructor.
When calling super().__init__ in the child class the child's method is executed instead of the parent's one inside the parent's constructor.
Example:
class A:
def __init__(self):
self.method()
def method(self):
print('parent method!')
class B(A):
def __init__(self):
super().__init__()
def method(self):
print('child method!')
b = B()
Output: child method!
While I want to get parent method!
Edit:
I need the parent's class constructor to use the not-overriden method, but after that each call to method() from the parent class should call overriden one.
Because I need the parent's contructor to be called with the no-overriden method but then I need to use the overriden one each time.
This indicates you are asking one method to do too many things. Split method into two parts: one that is not overridden and called by A.__init__, and another that can be overriden. Something like
class A:
def __init__(self):
self._init_method()
def _init_method(self):
print('parent method!')
def method(self):
self._init_method()
class B(A):
def __init__(self):
super().__init__()
def method(self):
print('child method!')
b = B()
_init_method does what you claim needs to be done from A.__init__. At the same time, you can have method do the same thing, unless you override it, in which case you'll do whatever it is you want B.method to do.
If you have that kind of situation, I would suggest something like:
class B(A):
def __init__(self):
super().__init()
self.n_method = 1
def method(self):
if self.n_method == 1:
super().method()
else:
do method B stuffs
self.n_method += 1
In A's __init__() method, you could write A.method(self) rather than self.method() to be more explicit about which method to call.

How to bring variables of super method into child method in Python3

I am implementing a subclass Child where an overwritten method some_method calls the parent method first. I want to use variable a from the parent method in the child method. Is there a neat way to do this without having to modify the code of Parent?
class Parent:
def __init__(self):
pass
def some_method(self):
a = 0
class Child(Parent):
def __init__(self):
super().__init__()
def some_method(self):
super().some_method()
b = a - 1 # Here I would like to keep using `a`

Classes, Objects, Inheritance?

I'm supposed to create three classes: a parent, and child 1 and child 2.
Child 1 and 2 are supposed to inherit from the Parent class.
So I believe I've done that.
class Parent:
"""Parent Object"""
def __init__(self):
self.greeting = "Hi I'm a Parent Object!"
class ChildA(Parent):
def __init__(self):
childclass.__init__(self)
self.childgreeting = "Hi I'm a Child Object!"
class ChildB(Parent):
pass
Now I have to write a parent object and the children objects which will print out their respective strings.
That's where I'm getting confused: I already put in the strings that they are a child or parent object within their classes.
But how do I get them to print as an object?
I've started out my code like this.
class Parent(object):
class ChildA(object):
class ChildB(object):
How to get those strings to print is bugging me.
And I have a feeling that my ChildA code for the class is not correct either.
Can anyone help me?
Child 1 and 2 are supposed to inherit from the Parent class. So I believe I've done that
Yes, in the first code, you have, but not in the second code.
I have to write a parent object and child 1 and 2 objects that will print out their respective strings
Okay...
p = Parent()
child_a = ChildA()
print(p.greeting)
print(child_a.childgreeting)
However - ChildA() won't work because __init__ should look like this
class ChildA(Parent):
def __init__(self):
super().__init__() # This calls the Parent __init__
self.childgreeting = "Hi I'm a Child Object!"
Now, the above code will work.
But, I assume you want the greeting attribute to be overwritten? Otherwise you get this
print(child_a.greeting) # Hi I'm a Parent Object!
print(child_a.childgreeting) # Hi I'm a Child Object!
If that is the case, you simply change childgreeting to greeting. Then, from the first example
print(p.greeting) # Hi I'm a Parent Object!
print(child_a.greeting) # Hi I'm a Child Object!
how do I get them to print as an object?
Not entirely sure what you mean by that, but if you define __str__ to return greeting
class Parent:
"""Parent Object"""
def __init__(self):
self.greeting = "Hi I'm a Parent Object!"
def __str__(self):
return self.greeting
The example now becomes
print(p) # Hi I'm a Parent Object!
print(child_a) # Hi I'm a Child Object!
class Parent(object):
def __init__(self):
self.greeting = "Hi I am a parent"
def __str__(self):
return self.greeting
class Child(Parent):
def __init__(self):
super(Child, self).__init__()
self.greeting = "Hi I am Child"
def __str__(self):
return self.greeting
p = Parent()
print(p)
c = Child()
print(c)
This method could help you to use 'print()' statement to print out greeting for individual class. But if you want to directly get self.greeting attribute you should use
p = Parent()
print(p.greeting)
Hope I understood you since your questions seems to be not properly explained...

Access parent class instance attribute from child class instance?

How to access "myvar" from "child" in this code example:
class Parent():
def __init__(self):
self.myvar = 1
class Child(Parent):
def __init__(self):
Parent.__init__(self)
# this won't work
Parent.myvar
child = Child()
Parent is a class - blue print not an instance of it,
in OOPS to access attributes of an object it requires instance of the same,
Here self/child is instance while Parent/Child are classes...
see the answer below, may clarify your doubts.
class Parent():
def __init__(self):
self.myvar = 1
class Child(Parent):
def __init__(self):
Parent.__init__(self)
# here you can access myvar like below.
print self.myvar
child = Child()
print child.myvar
Parent does not have an attribute called myvar. Only instances of parent have that attribute. From within a method of Child, you can access that attribute with self.myvar.
Alternative to using inheritance
The current answers are coming from an inheritance perspective, but this isn't always what you want -- sometimes you might want the child to be an entirely different type of object to the parent, but that still has access to the parent attributes.
For a business analogue, think of Excel Workbooks which have Worksheet children, which themselves have Range children, and so on.
Only Child
An alternative approach (and not the only one) is to pass the parent as an argument to the child to create a property that corresponds to the parent:
class Parent(object):
def __init__(self, parent_value):
self.parent_value = parent_value
self.child = Child(self)
class Child(object):
def __init__(self, _parent):
self.parent = _parent
self.child_value = 0
new_parent = Parent(1)
print(new_parent.parent_value) # prints 1
new_child = new_parent.child
print(new_child.child_value) # prints 0
print(new_child.parent.parent_value) # prints 1
new_parent.parent_value = 100
print(new_child.parent.parent_value) # prints 100
Note that this instantiates the child at the same that that new_parent is instantiated. To access the parent's attributes, just go through the parent property.
Multiple Children
You could extend this so that you can create multiple instances of the Child class through the new_parent object. The code below is one simple way of doing this which replaces the child property with a children property and an add_child method.
class Parent(object):
def __init__(self, parent_value):
self.parent_value = parent_value
self.children = []
def add_child(self, child_value):
new_child = Child(child_value, _parent=self)
self.children.append(new_child)
return new_child # allows add_child to assign a variable
class Child(object):
def __init__(self, child_value, _parent):
self.parent = _parent
self.child_value = child_value
new_parent = Parent(1)
# add 3 Child instances with child_values 2, 4, 8
[new_parent.add_child(v) for v in [2, 4, 8]]
# add another child that utilises the return statement
extra_child = new_parent.add_child(16)
for child in new_parent.children:
print(child.child_value) # prints 2, 4, 8, 16
print(child.parent.parent_value) # prints 1
new_parent.parent_value = 32
for child in new_parent.children:
print(child.parent.parent_value) # prints 32
# prove that extra_child is new_parent.children[3]
extra_child.child_value = 64
print(new_parent.children[3].child_value) # prints 64
You need to initiate the parent class first via so-called proxy object using command "super".
So the code will be like this:
class Parent():
def __init__(self):
self.myvar = 1
class Child(Parent):
def __init__(self):
super.__init__()
child = Child()
print child.myvar

Categories

Resources