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
Related
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())
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)
I am trying to subclass a python class and overwrite a regular attribute with a #property function. The catch is that I can't modify the parent class, and the api for the child class needs to look the same as the parent class (but behave differently). (So my question is different from this one in which the parent class also used a #property method to access the underlying attribute.)
The simplest possible example is
# assume this class can't be overwritten
class Parent(object):
def __init__(self, a):
self.attr = a
# how do I make this work?
class Child(Parent):
def __init__(self, a):
super(Child, self).__init__(a)
# overwrite access to attr with a function
#property
def attr(self):
return super(Child, self).attr**2
c = Child(4)
print c.attr # should be 16
This produces an error when the parent init method is called.
<ipython-input-15-356fb0400868> in __init__(self, a)
2 class Parent(object):
3 def __init__(self, a):
----> 4 self.attr = a
5
6 # how do I make this work?
AttributeError: can't set attribute
Hopefully it is clear what I want to do and why. But I can't figure out how.
This is easily fixed by adding a setter method
class Child(Parent):
def __init__(self, a):
self._attr = None
super(Child, self).__init__(a)
# overwrite access to a with a function
#property
def attr(self):
return self._attr**2
#attr.setter
def attr(self, value):
self._attr = value
Suppose I have the following class in Python 3:
class CoolCar:
#classmethod
def myWheels(cls):
cls.Wheels().out()
class Wheels:
def __init__(self):
self.s = "I'm round!"
def out(self):
print(self.s)
All well and good. Now I want a derived class:
class TerribleTank(CoolCar):
class Wheels(CoolCar.Wheels):
def __init__(self):
self.s = "I'm square!!"
This works as I would expect:
CoolCar.myWheels()
TerribleTank.myWheels()
But what's bothering me is that I have to write CoolCar twice in the definition of TerribleTank. So I tried this:
class TerribleTank(CoolCar):
class Wheels(super().Wheels):
def __init__(self):
self.s = "I'm square!!"
Which does not work. Now, I know it doesn't work because super() is looking for a first-argument self/cls to begin its search.
So finally my question: Is there something like this that works, so that I don't need to explicitly write that second CoolCar?
What about:
class CoolCar:
#classmethod
def myWheels(cls):
cls.Wheels().out()
class Wheels:
def __init__(self):
self.s = "I'm round!"
def out(self):
print(self.s)
class TerribleTank(CoolCar):
class Wheels(TerribleTank.Wheels):
def __init__(self):
self.s = "I'm square!!"
>>> TerribleTank.myWheels()
I'm square!!
basically when you inherit CoolCar in TerribleTank, you set up TerribleTank.Wheels as a reference to CoolCar.Wheels, until you shadow it with your own new definition of it within the TerribleTank definition. So I believe that matches your expectations of not having CoolCar twice in TerribleBank definition ☺
HTH
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())