Using __init__ and inheritance in python - python

I'm a little confused regarding using __init__ and inheritance and would love to get some help with it.
I have a class [that can not be changed]:
class A(object):
def __init__(self, param1 = 7, param2 = 10):
self.x = param1
self.y = param2
def func1(self):
op1()
op2()
def func2(self):
pass
this is some class that was written and I'm using it when overloading its functions:
class B(A):
def func1(self)
op3()
op4()
def func2(self)
op5()
My problem starts here : I want to use Class B several times and sent each time different parameter:
---new .py file: ---
def myFunction():
myInstance = B()
I want to do something like :
def myFunction():
myInstance = B(40,"test")
I thought adding to B class - __init__ but the problem is that now I'm not sure what self it would use :
explanation :
Inside B class I have overloaded func2(self)
I thought writing :
class B(A):
def __init__(self, paramNumber, paramString)
self.paramNumber = paramNumber
self.paramString = paramString
but now in func2(self) , what self is used? the new one? the old one? will it work?
meaning I will have : self.x , self.y and self.paramNumber self.parmString ?they are different "selfs"
Editing :
Should I use super as well?
class B(A):
def __init__(self, paramNumber, paramString,param1, param2)
self.paramNumber = paramNumber
self.paramString = paramString
super(B,self).__init__(param1,param2)
def myFunction():
myInstance = B(40,"test")
// I will get : self.x = 7
// self.y= 10
// self.paramNumber=40
//self.paramString = "test"
is this the correct solution?

So basically you want to run __init__ from parent class inside child:
class B(A):
def __init__(self, paramNumber, paramString):
super(B, self).__init__(param1=1, param2=2)
# the other code goes here

Related

Python: Using property get/set to run on sub-class function

I have a setup that looks something like this simplified setup:
class WorkerBee():
def __init__(self):
self.x = 1
self.old_x = None
def update_x(self, val):
self.update_old_x()
self.x = val
def _update_old_x(self):
self.old_x = self.x
class MainClass():
def __init__(self):
self.bee = WorkerBee()
def updated_WorkerBee(self):
print('yay, it was updated')
I understand the use of #property to do a get - set setup for an attribute. But in this case, I'm trying to figure out how I can directly call the WorkerBee methods (there are more than 1 in my case....) that would also trigger MainClass.updated_WorkerBee()
In:
main = MainClass()
main.bee.update_x(2)
Out:
yay, it was updated
Any help is appreciated!
You could add a reference to the main object to the bee, like a parent:
class WorkerBee:
def __init__(self, main):
self.main = main
self.x = 1
(...)
and then use it in your update methods within WorkerBee, to update main too:
def update_x(self, val):
self.update_old_x()
self.x = val
self.main.updated_WorkerBee()
To do that, pass the main to the bee when you create it:
class MainClass:
def __init__(self):
self.bee = WorkerBee(self)

Python: pass whole self of class to init of new class

I have a class and a sub-class, I'd like to pass the whole of the self of the class to the sub-class. I can pass self over to the new class explicitly easily enough, e.g.
class foo:
def __init__(self, a, b):
self.a = a
self.b = b
self.c = 'foo'
def foo_method(self):
print('a foo method')
class bar(foo):
def __init__(self, foo_object):
self.a = foo_object.a
self.b = foo_object.b
self.c = foo_object.c
def bar_method(self):
print('a bar method')
foo_object = foo(a = 'a', b = 'b')
bar_object = bar(foo_object)
bar_object.a
Is there a more succinct way to pass these over? Something like:
class bar(foo):
def __init__(self, foo_object):
self = self.foo_object
Update:
Thanks https://stackoverflow.com/users/10104112/bastien-antoine, the following solution worked:
class bar(foo):
def __init__(self, foo_object):
self.__dict__ = foo_object.__dict__.copy()
def bar_method(self):
print('a bar method with ' + str(self.c))
Have you tried the copy builtins library?
Otherwise I think you can easily implement your own .copy() method that would copy the values from the old object __dict__ to the new one. Something like this:
class MyObject:
a = None
def set_default_values(self):
self.a = 1
def copy(self, old):
if type(self) == type(old):
self.__dict__ = old.__dict__.copy()
else:
raise TypeError('Wrong type')
if __name__ == "__main__":
obj_1 = MyObject()
print(obj_1.a)
obj_1.set_default_values()
print(obj_1.a)
obj_2 = MyObject()
print(obj_2.a)
obj_2.copy(obj_1)
print(obj_2.a)
Note that I've added a type checking to be sure that you copy attributes that would exist otherwise, but I think simply self.__dict__ = old.__dict__.copy() would work fine, thought you might end up with attributes you might not suppose to have in the new object.
Hope this helps!
I think that you can do that with
class bar(foo):
def __init__(self):
super(bar, self).__init__()
with this code, you ran the init function for the subclass

Python class static method that requires another static method

Is it ok to have multiple staticmethods that calls from each other.
something like:
class Myclass():
def __init__(self, a):
self.var = self.static1(a)
#staticmethod
def static1(i):
i += 1
return self.static2(i)
#staticmethod
def static2(i):
return i * 3
c = Myclass(1)
I got :
NameError: name 'self' is not defined
use the #classmethod decorator
function will denote it does not change anything in the instance while you can access the class via first parameter cls
class Myclass():
def __init__(self, a):
self.var = self.static1(a)
#classmethod
def static1(cls,i):
i += 1
return cls.static2(i)
#staticmethod
def static2(i):
return i * 3
No need to prepend with 'self.'. Just call MyClass.static2(i)

Nested classes that inherit from the outer parent's nested classes in Python 3

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

Why we using super() when inherit is already enough

I saw an example that is about super();
class Class1:
def __init__(self):
pass
def name(self):
return "My name is"
class Class2(Class1):
def __init__(self):
pass
def name(self):
return super(Class2, self).name() + " Tom"
#now lets call the object.
b = Class2()
print(b.name())
#Output is 'My name is Tom'
Here is another version of this one without super() that I made on the above codes;
class Class1:
def __init__(self):
pass
def name(self):
return "My name is"
a = Class1()
class Class2(Class1):
def __init__(self):
pass
def name(self):
return a.name() + " Tom"
b = Class2()
print(b.name())
Output is same. So while we can inherit the abilites from Class1, we can use that abilities already. Then why we need super() ?
Because you're using the wrong example. Try to do this without super():
class Base:
def __init__(self, x):
self.x = x
def square(self):
return self.x**2
class Derived(Base):
def __init__(self, x, y):
super().__init__(x)
self.y = y
def square(self):
return super().square() + self.y**2
class CubeMixin(Base):
def square(self):
return self.x**3
class MultiplyDerived(Derived, CubeMixin):
pass
Edited to use multiple inheritance, per chepner in the comments.
When Derived calls super().square(), it gets CubeMixin.square(), rather than Base.square(). If it hadn't used super(), there would be no way for it to know that CubeMixin.square() even existed.
What you did here is called composition, although you missed it by a little.
For large codebase it's generally considered a better approach, because it alleviates issues with debugging. Imagine you had a class that inherited a class which inherited a class... After a while it tends to get hard to keep up. Proper example of a composition would be:
class a(object):
def __init__(self, a):
self.a = a
class b(object):
def __init__(self, b):
self.b = b
class rect(object):
def __init__(self, x, y):
self.a = a(x)
self.b = b(y)
Which seems a bit silly for something stupid, but has pretty much the same uses as inheritance. Additionally, it may take a bit more code (a decorator) to make the class instances not behave like objects so you don't bother the end user.
Get a better example, and comparison composition vs inheritance Here

Categories