What is the issue with inheritance in this code? - python

class a(object):
def __init__(self):
self.num1=0
self.num2=0
def set1(self,score1,score2):
self.num1=score1
self.num2=score2
def show1(self):
print("num1",self.num1,"num2",self.num2)
class b(a):
def __init__(self):
super().__init__()
def set2(self):
self.sum=self.num1+self.num2
def show2(self):
print("d=",self.sum)
class c(b):
def __init__(self):
super.__init__()
def set3(self):
self.multiplication=self.num1*self.num2
def show3(self):
print("f=",self.multiplication)
objects=c()
objects.set1(1000,100)
objects.show1()
objects.set2()
objects.show2()
objects.set3()
objects.show3()
I wrote this code to work on the meaning of inheritance, but I receive:
objects=c()
File "C:\Users\user\Desktop\New folder\2.py", line 23, in __init__
super.__init__()
TypeError: descriptor '__init__' of 'super' object needs an argument
num1 and num2 are two numbers and I want to calculate sum and multiplication of them via concept of inheritance in Python.
I do not know what is the problem with.What is the problem with this code?
Thanks,

You wrote super.__init__() instead of super().__init__() in __init__ of class c.
If you are using Python 2 you will need to call super in the following way: super(ClassName, self).__init__().

You need to call super, right now its just a reference.
class c(b):
super().__init__()
The other thing is that if you wanted to make this inheritance more robust, you could pass through all args and kwargs to __init__ like so:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
This would make your classes more flexible, and open to multiple inheritance.

I think it's how you used the super() built-in Here the doc
In your case, super need two argument: the class and an instance of the class.
In your b.__init__ the synthax will be:
super(b,self).__init__()
here the solution for your problem:
class b(a):
def __init__(self):
super(b, self).__init__()
def set2(self):
self.sum=self.num1+self.num2
def show2(self):
print("d=",self.sum)
class c(b):
def __init__(self):
super(c, self).__init__()
def set3(self):
self.multiplication=self.num1*self.num2
def show3(self):
print("f=",self.multiplication)

Related

Not being able to inherit the logger [duplicate]

Consider the following code:
class A(object):
def __init__(self):
pass
class B(object):
def __init__(self):
self.something = 'blue'
def get_something(self):
return self.something
class C(A,B):
def __init__(self):
super().__init__()
print(self.get_something())
and then do:
c = C()
which results in something like this:
AttributeError: 'C' object has no attribute 'something'
I suppose this happens due to the constructor of B not being called when using super(). Is there a way to achieve the correct behavior with Python 3?
Superclasses should use super if their subclasses do. If you add the super().__init__() line into A and B your example should work again.
Check the method resolution order of C:
>>> C.mro()
[__main__.C, __main__.A, __main__.B, builtins.object]
This article should clear things up.
As others have mentioned, the method resolution order is key here. If you want to call multiple superclass constructors, then you will have to call them directly.
class A(object):
def __init__(self):
pass
class B(object):
def __init__(self):
self.something = 'blue'
def get_something(self):
return self.something
class C(A,B):
def __init__(self):
A.__init__(self)
B.__init__(self)
print(self.get_something())

How to get self.value from an inherited class?

I have this two classes that I needed to divide, though they share some common features. Is it possible to access first class' self.value from the second class? Please look at the pseudo code, surely more understandable then my words.
class a:
def __init__(self):
self.value = 45
class b(a):
def __init__(self):
self.other_value = #this should be self.value from class a
You need call the parent constructor first
class B(A):
def __init__(self):
super().__init__()
print(self.value)
you should call the parent constructor:
class b(a):
def __init__(self):
a.__init__(self)
#now you can use it with self.value

Multiple Mixins and properties

I am trying to create a mixin class that has it's own properties, but as the class has no init to initialize the "hidden" variable behind the property.
class Software:
__metaclass__ = ABCMeta
#property
def volumes(self):
return self._volumes
#volumes.setter
def volumes(self, value):
pass
class Base(object):
def __init__(self):
self._volumes = None
class SoftwareUser(Base, Software):
def __init__(self):
super(Base, self).__init__()
So above is the best that I have come up with to solve this but the reality is that the _volumes dosn't really belong in the base. I could add an init to the Software class but then the super call wont work on both mixins.
The second is that I will need multiple mixins dependent on the incoming call they will always need the base, but the mixins will change so I dont really want variables from mixins that aren't mixed in for that call.
Is there a way that i can have the mixin add it's variables to the class if it is mixed in perhaps dynamically call the init of the mixin class ?.
Any questions let me know.
Thanks
Yes, that's wildly overcomplicated. A class (including mixins) should only be responsible for calling the next implementation in the MRO, not marshalling all of them. Try:
class Software:
#property
def volumes(self):
return self._volumes
#volumes.setter
def volumes(self, value):
pass
def __init__(self):
self._volumes = None
super().__init__() # mixin calls super too
class Base(object):
def __init__(self):
other_vars = None
class SoftwareUser(Software, Base): # note order
def __init__(self):
super().__init__() # all you need here
Ok so here is what I came up with, I am open to other answers, if I have made this way over complicated.
class Software:
#property
def volumes(self):
return self._volumes
#volumes.setter
def volumes(self, value):
pass
def __init__(self):
self._volumes = None
class Base(object):
def __init__(self):
other_vars = None
class SoftwareUser(Base, Software):
def _bases_init(self, *args, **kwargs):
for base in type(self).__bases__:
base.__init__(self, *args, **kwargs)
def __init__(self, *args, **kwargs):
self._bases_init(*args, **kwargs)

Python multiple inheritance constructor not called when using super()

Consider the following code:
class A(object):
def __init__(self):
pass
class B(object):
def __init__(self):
self.something = 'blue'
def get_something(self):
return self.something
class C(A,B):
def __init__(self):
super().__init__()
print(self.get_something())
and then do:
c = C()
which results in something like this:
AttributeError: 'C' object has no attribute 'something'
I suppose this happens due to the constructor of B not being called when using super(). Is there a way to achieve the correct behavior with Python 3?
Superclasses should use super if their subclasses do. If you add the super().__init__() line into A and B your example should work again.
Check the method resolution order of C:
>>> C.mro()
[__main__.C, __main__.A, __main__.B, builtins.object]
This article should clear things up.
As others have mentioned, the method resolution order is key here. If you want to call multiple superclass constructors, then you will have to call them directly.
class A(object):
def __init__(self):
pass
class B(object):
def __init__(self):
self.something = 'blue'
def get_something(self):
return self.something
class C(A,B):
def __init__(self):
A.__init__(self)
B.__init__(self)
print(self.get_something())

Can I pass python **kwargs to parent class from sub?

I'd like to do something like this:
class A(object):
def __init__(self, **kwargs):
"""
return exception if certain arguments not set
"""
class B(A):
def __init__(self, **kwargs):
super(B, self).__init__(**kwargs)
Basically, each subclass will require certain arguments to be properly instantiated. They are the same params across the board. I only want to do the checking of these arguments once. If I can do this from the parent init() - all the better.
Is it possible to do this?
Sure. This is not an uncommon pattern:
class A(object):
def __init__(self, foo, bar=3):
self.foo = foo
self.bar = bar
class B(A):
def __init__(self, quux=6, **kwargs):
super(B, self).__init__(**kwargs)
self.quux = quux
B(foo=1, quux=4)
This also insulates you a little from super shenanigans: now A's argspec can change without requiring any edits to B, and diamond inheritance is a little less likely to break.
Absolutely. Parameter and keyword expansion will work naturally when fed into parameter and keyword arguments.

Categories