Inherit from a "sibling" class? - python

Imagine I have:
class ABC():
def main(self, x):
self.x = x
class A(ABC):
def afunction(self):
self.a = 2
class B(ABC):
def bfunction(self):
self.b = self.a * self.x
return self.b
How is it possible that class B inherits the self.a and self.x from class A and ABC? (I do not care about inheriting the methods)

If I understand correctly, what you want is to get B to inherit from A.
Notice that what will happen is that it will inherit A variables, and because A inherits from ABC, B will inherit ABC's variables as well.
Also, please note that you will have to initialize the x variable for example inside an B object in order to use the bFunction, and in general it is proper coding to set a constructor as follows:
class ABC():
def __init__(self, x=0):
self.x = x
def main(self, x):
self.x = x
class A(ABC):
def __init__(self, a=2):
super().__init__()
self.a = a
def afunction(self):
self.a = 2
class B(A):
def __init__(self, b=0):
super().__init__()
self.b = b
def bfunction(self):
self.b = self.a * self.x
return self.b
b = B()
b.main(3)
b.afunction()
print(b.bfunction())
Output:
6

If B inherits from A, which inherits from ABC, then B will have ABC and A's methods but neither the 'x' or 'a' attributes which are only set after the methods are run. This works if you rewrite B as:
class B(A):
def bfunction(self, x):
self.main(x)
self.afunction()
self.b = self.a * self.x
return self.b
b = B()
print(b.bfunction(10))
You have to supply 'x' to b.bfunction so that self.b = self.a * self.x works.

Related

Correct usage of self in Python classes [duplicate]

This question already has answers here:
What is the purpose of the `self` parameter? Why is it needed?
(26 answers)
Closed 4 months ago.
In the example below, classes AA and BB are instantiated with params a and b and feature the foo method. The only difference between classes AA and BB is that in the AA foo method, the intermediate variable z is prefixed with the class instance reference self while in class BB it is not. What is the correct methodology here? When should self be used within class methods and when should it not be used? I've always been confused by this!
class AA:
def __init__(self, a, b):
self.a = a
self.b = b
def foo(self):
self.z = self.a + self.b
return self.z * self.a
class BB:
def __init__(self, a, b):
self.a = a
self.b = b
def foo(self):
z = self.a + self.b
return z * self.a
Neither one is "correct" per se. It depends what you want to do: If you want to keep the value around, then you could assign it to the instance. If not, then don't.
Although, if you do assign it as a public instance attribute, you'll probably want to set an initial value in __init__(), like None.
the use of the self will appear when you initiate an object from the class, so in order that the object will have an access to the variable you need to use the self
class AA:
def __init__(self, a, b):
self.a = a
self.b = b
def foo(self):
self.z = self.a + self.b
return self.z * self.a
class BB:
def __init__(self, a, b):
self.a = a
self.b = b
def foo(self):
z = self.a + self.b
return z * self.a
A = AA(1, 2)
A.foo()
print(A.z) # will print the value
B = BB(1, 2)
B.foo()
print(B.z) # will not print the value, "z" attribute is not defined

python 3 class inheritance issue

class A(object):
def __init__(self):
self.a = 1
class B(A):
def __init__(self):
A.__init__(self)
self.a = 2
self.b = 3
class C(object):
def __init__(self):
self.a = 4
self.c = 5
class D(C, B):
def __init__(self):
C.__init__(self)
B.__init__(self)
self.d = 6
obj = D()
print(obj.a)
My understanding is that python will first search class C then B then A to get a. So print(obj.a) will print out 4 when searching class C. But the answer is 2. This means that Python got self.a = 2 from class B instead of self.a = 4 from class C. Can anyone explain the reasons? Thank you
There is no search going on here. You are making explicit, direct calls to unbound methods, passing in self manually. These are simple function calls, nothing more.
So this is just a question of tracing the execution order:
D() -> D.__init__(self)
C.__init__(self)
self.a = 4
B.__init__(self)
A.__init__(self)
self.a = 1
self.a = 2
So a is assigned 4, then 1, then 2.

Python Inheritence Subclass(ing)

Given a parent class 'A'
class A(object):
def __init__(self,a,b):
self.a = a
self.b = b
def methodA():
# do something
What is the difference between making a subclass 'B' among the below options
Option 1
class B(A):
def methodB():
# do something
Option 2
class B(A):
def __init__(self,a,b):
A.__init__(self, a, b)
def methodB():
# do something
class A(object):
def __init__(self,a,b):
self.a = a
self.b = b
class B(A):
def __init__(self,a,b):
A.__init__(self, a, b)
def methodB():
pass
class C(A):
def methodB():
pass
b = B(1,2)
c = C(1,2)
print b.a == c.a # True
print b.b == c.b # True
In both class instantiation, init under class A will be ran only once.
so no, there is nothing significantly different.
class B is not clean IMO and poses no real purpose at all. It will be ran anyways.
If you wish to do something different in class B init, then yes, you can use this code.
class B(A):
def __init__(self,a,b):
A.__init__(self, a+1, b+1)
def methodB():
pass

Super with arguments in case of multiple inheritance

I have a class that inherits from two other classes whose __init__ take both a parameter like this:
class A(object):
def __init__(self, a):
self.a = a
class B(object):
def __init__(self, b):
self.b = b
class C(A, B):
def __init__(self, a, b):
super(C, self).__init__(a, b)
c = ClassC(1, 2)
This gives a TypeError: __init__() takes exactly 2 arguments (3 given).
When setting b in B to a fixed value and passing only 1 parameter to super then trying to access b in C gives an AttributeError: 'ClassC' object has no attribute 'b':
class A(object):
def __init__(self, a):
self.a = a
class B(object):
def __init__(self, b):
self.b = 2
class C(A, B):
def __init__(self, a, b):
super(C, self).__init__(a)
print self.a
print self.b
c = ClassC(1, 2)
When calling the __init__ manually everything seems to be fine:
class A(object):
def __init__(self, a):
self.a = a
class B(object):
def __init__(self, b):
self.b = b
class C(A, B):
def __init__(self, a, b):
A.__init__(a)
B.__init__(b)
print self.a
print self.b
c = ClassC(1, 2)
So how can I get this inheritance straight and how can I manage the parameters for __init__ of inherited classes when using super? Is it even possible? How does super know which parameters are to pass to which class?

python classes dependant on eachother, how to init?

I have two classes:
class A(object):
def __init__(self, b):
self b = b
class B(object):
def __init__(self, a):
self a = a
I'd like to init them like this:
a = A(b)
b = B(a)
But I can't since 'b' doesn't exist when doing a = A(b). I have to do:
a = A()
b = B(a)
b.a = a
But that seems unclean. Is this solvable?
You could either make one class instantiate the other:
class A(object):
def __init__(self):
self.b = B(self)
class B(object):
def __init__(self, a):
self.a = a
a = A()
b = a.b
Or make one class tell the other about itself, like this:
class A(object):
def __init__(self, b):
self.b = b
b.a = self
class B(object):
def __init__(self):
#Will be set by A later
self.a = None
b = B()
a = A(b)

Categories