Changing base class in a inheritance hierarchy - python

I have a class structure like
class A:
def method1(self):
return 1
class B:
def method2(self):
return 2
class C(A,B):
def method3(self):
return self.method1()+self.method2()
The Classes A and B provide functionality which class C gathers and enriches with some wrappers. Now it happens that I need a similar class C2 which is derived from a different implementation A2 instead of A: class C2(A2, B) with the same method3.
How would you realize such a design (C can derive from different implementation classes)?
If it has to do with advanced Python programming (meta-classes?) an example would be appreciated :)

class CMixin:
def method3(self):
return self.method1()+self.method2()
class C1(A,B, CMixin):
pass
class C2(A2,B, CMixin):
pass
Though the design you describe sounds like you want aggregation instead:
class C:
def __init__(self, a, b):
self.a = a
self.b = b
def method3(self):
return self.a.method1() + self.b.method2()
c1 = C(a1, b)
c2 = C(a2, b)

Related

How to initialise subclasses when the parent class uses a classmethod?

So let's say I have this code structure:
class Parent:
def __init__(self, a, b, c):
self.a = a,
self.b = b
self.c = c
#classmethod
def from_string(cls, some_string):
if some_string == 'duh':
return cls(a=5, b=6, c='banana')
else:
return cls(a=0, b=0, c='chicken')
def method_1(self):
#do something
def method_2(self):
#do something else
class FirstChild(Parent):
def __init__(self, a, b, c):
super().__init__(a, b, c)
def child_specific_method(self):
#do something
class SecondChild(Parent):
def __init__(self, a, b):
super().__init__(a, b)
def some_other_method(self):
#do stuff
My thinking was that I want both subclasses to have access to methods of the Parent class, but also extend its functionality. At the same time I want the Parent class to instantiate with different parameters based on the class method.
Now I'm confused as to how I would create instances of child classes? Or, more precisely, how would I create child instances when there can be different versions of the parent class?

Asking some tips for using init in python

I tried to find out with googling, but it seems not explained.
There are four classes, for example, which are A, B, C, and D.
C is sub-class of D. A and B is calling C.
Class A:
def __init__(self):
self.c = C()
Class B:
def __init__(self):
self.c = C()
Class C(D):
def __init__(self):
print('it is C')
Class D:
def __init__(self):
print('it is D')
a = A()
b = b()
In this case, it will initiate twice for Class C. So, 'it is C' and 'it is D' strings represent twice. And.. I think it's ... not normal.
Unlike Java, it seems that Python doesn't support constructor overloading.
In this case, can I call C only though? Or, could I get an advice for using init in Python?
Thank you.
You have several errors in your code: class not Class, checkout indentation, class definition order... see this:
class D:
def __init__(self):
print('it is D')
class C(D):
def __init__(self):
print('it is C')
class A:
def __init__(self):
self.c = C()
class B:
def __init__(self):
self.c = C()
a = A()
b = B()
method 1
you can use the *args and **kwargs
args and kwargs
you can get the len(args) and len(kwargs.keys()) (kwargs is a dict) and program different parts depending on the number of arguments. this can work like a constructor overloading
example:
__init__(self, *args):
if len(args)==0:
# constructor one
if len(args)==1:
# constructor two
method 2
use default arguments, most likely argname=None. then use if-else with the value of that argument
simple example :
__init__(self, arg1=None):
if arg1==None:
# constructor one
else:
# constructor two

How to overwrite abstract method of a child class of a super class, from the inheriting class?

I have a class KA, which has two methods, add() and subtract(), and an abstract child class KAX. KAX has an abstract method, multiply(). There is another class KB which inherits KA, and by extension has access to KAX.multiply(). I would like to overwrite/define KAX.multiply() from class KB. How to do this?
So far what I could think of is define a private method __multiply() under class KB, and then redefine under KB.__init__() as follows:
self.KAX.multiply = self.__multiply()
This works. However, I am wondering if there is a better way to do what I am trying to achieve here. Thank you.
My current code:
from abc import ABC, abstractmethod
class KA():
def __init__(self):
self.A = 3
self.B = 10
self.C = self.B**self.A
#abstractmethod
def add(self): pass
#abstractmethod
def subtract(self): pass
class KAX(ABC):
#abstractmethod
def multiply(self): pass
class KB(KA):
def __init__(self, A = 3, B = 10):
#super(KB, self).__init__()
self.A = A
self.B = B
self.KAX.multiply = self.__multiply
self.KAX.multiply()
self.C = self.KAX.multiplication
def add(self):
self.addition = self.A + self.B
def subtract(self):
self.subtraction = self.A - self.B
def __multiply(self):
self.KAX.multiplication = self.A*self.B
if __name__ == '__main__':
kb = KB(A = 4, B = 2)
# check values of variables: A, B, C
print('Parameters: A, B, C')
print(''.join(['kb.{}: {}\n'.format(vname, getattr(kb,vname)) for vname in ['A', 'B', 'C']]))
# apply methods
kb.add()
kb.subtract()
kb.KAX.multiply()
# show results
result_string = 'Result: \n\t addition: {}\t | subtraction: {}\t | multiplication: {}'
print(result_string.format(kb.addition, kb.subtraction, kb.KAX.multiplication))
The output of this code results in:
Parameters: A, B, C
kb.A: 4
kb.B: 2
kb.C: 1000
Result:
addition: 6 | subtraction: 2 | multiplication: 8
KAX isn't a child class, it's just a class defined within another class. So, you can subclass it and override its methods:
class KB(KA):
class KAX(KA.KAX):
def multiply(self):
print("hello!")
Maybe you could try making a new class called KB.KAX that extends KA.KAX and then implementing your method like so:
class KA():
class KAX():
#abstractmethod
def multiply(self): pass
class KB(KA):
class KAX(KA.KAX):
def multiply(self):
print("doing stuff")

Class inheritance, how to improve?

i have a little question that is discouraging me i have this portion of code:
class A(object):
def __init__(self):
self.variable = "Hello World!!!"
class B(A):
def __init__(self):
self.A = A()
self.inherited = self.A.variable
the thing is that i have a bunch of variables on class A that i don't want to instantiate and declare on class B one by one
is there a way to improve the code?
You are using a mix of composition and inheritance. It seems like you want to exclusively use composition:
class A(Object):
def __init__(self):
self.c = C()
self.e = E()
class B(Object):
def __init__(self):
self.c = C()
self.d = D()
Where C, D, and E are components that group variables and methods together. Now A and B only share the component of C. You should look for more complete composition tutorials
Edit: Actually just double checking it looks like your just confused about instantiating super class variables. Other answers correctly addressed this with super
You are misunderstanding two concepts.
For example, you are trying to do both composition and inheritance.
class A(Object):
def __init__(self):
self.variable = "Hello World!!!"
class B(A):
def __init__(self):
self.A = A()
self.inherited = self.A.variable
When you do this, you are saying, "Make B also an A object." In other words, the following works:
class A(object): # can omit this (object) in python3
def __init__(self):
self.value_from_a = 'Im from A!'
class B(A):
def __init__(self):
super().__init__()
self.value_from_b = 'im a bbbbb!'
b = B()
print(b.value_from_a)
print(b.value_from_b)
So, in your case the way to do this is to not try to make an A both the base as well as part of B.
Note if you are using Python2 the above syntax will be slightly different.

How can i have 2 classes reference the same instance of a class

I have class A class B and class C.
class A and B can affect class C. so they need to refer to the same instance of the class.
#a.py
from C import C
Cinstance = C()
Cinstance.add()
#b.py
class b(object)
#i need to refer to 'cinstance' here to control the same instance of the class
#C.py
class C(object)
def __init__(self):
self.a=1
def add(self):
self.a += 1
print a
How do i need to import and instanciate the classes for it to work this way? I am new to programming and still learning so things that are obvious are still a little difficult for me right now.
class A:
def __init__(self,cInst):
self.c = cInst
class B:
def __init__(self,cInst):
self.c = cInst
cInst = C()
a = A(cInst)
b = B(cInst)
something like that maybe
based on what you have there I think the easiest thing would be to import Cinstance from module a.
from a import Cinstance
You can pass an instance of A and B to your C.__init__ method and save them as attributes of C.
I'm on my phone, so the code below isn't tested
class C(object):
def __init__(self, a, b):
self.a = a
self.b = b
>>> c = C(A(), B())

Categories