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

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`

Related

Expensive operation in parent class performed once for all child classes

I have two classes that inherit from the same base class. In the base class I have a very expensive method that must be ran only once and whose generated attributes must be available to the child class. How do I achieve that?
In the example below, the instantiation of the B and C child classes will both run expensive_op in A. I'd like expensive_op to be called only when I call b=B(). A is never called directly.
Moreover, I want to be able to modify the attributes of the parent class from the child class as done, for example, in the modify method in B.
Anyone able to help?
class A:
def __init__(self):
self.expensive_op()
def expensive_op(self):
self.something = #something ugly and expensive
class B(A):
def __init__(self):
super().__init__()
def modify(self,mod):
self.something = self.something+mod
class C(A):
def __init__(self):
super().__init__()
b = B()
c = C()
EDIT: in response to #0x5453's comment, do you mean the modification of A below?
class A:
def __init__(self):
self.something = None
def expensive_op(self):
if self.something is not None:
self.something = #something ugly and expensive
But if I call b=B() and then c=C(), the latter won't know about self.something. The output is
b=B()
c=C()
b.expensive_op(3)
print(b.something)
>>> 3
print(c.something is None)
>>> True
Am I missing something?

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.

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

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

Python inheriting instance variable when value of the variable changes dynamically

I have to inherit dynamic value of the Parent instance variable a.I've tried using super which gets the value which is defined in the init constructor of the Parent and also have tried passing Parent object.
Please refer the code snippet below
class Parent(object):
def __init__(self):
self.a = 1
def test(self):
self.a = 2
class Child(Parent):
def __init__(self):
super(Child, self).__init__()
class Child1(Parent):
def __init__(self, parent):
self.a = parent.a
p = Parent()
c = Child()
c1 = Child1(p)
p.test()
print p.a #2
print c.a #1
print c1.a #1
If I use below code, the problem gets solved.However is there any way to get the instance variable value of parent which is altered after initialization.
c.test()
print c.a #2
c1.test()
print c1.a #2
Please suggest any solution for this problem.
You need to use delegation here. Instead of directly assigning self.a to the value of parent.a, you should store the parent, and then define a property that gets the value of the parent's a on request.
class Child1(object):
def __init__(self, parent):
self.parent = parent
#property
def a(self):
return self.parent.a

Categories

Resources