I'm currently using this pattern to create a class C that inherits from A and B. I couldn't call super().__init__ from C since I would have to do the same in A and B, and the unexpected parameter would cause problems at the top level. I feel like this isn't very elegant. What is the proper way to do multiple inheritance in Python? I guess it is unusual to query the mro to find out if the superclass expects a parameter?
class A:
def __init__(self, something):
self.a = X(something)
def method_a(self):
self.a.go()
def method_ab(self):
self.a.go2()
class B:
def __init__(self, something):
self.b = X(something)
def method_b(self):
self.b.go()
def method_ab(self):
self.b.go2()
class C(A, B):
def __init__(self, something):
self.a_ = A(something)
self.b_ = B(something)
#property
def a(self):
return self.a_.a
#property
def b(self):
return self.b_.b
def method_ab(self):
for x in [self.a, self.b]:
x.method_ab()
The best solution I found was to use a base class to absorb the extra parameters:
class Base:
def __init__(self, something):
pass
def method_ab(self):
pass
class A(Base):
def __init__(self, something):
super().__init__(something)
self.a = X(something)
def method_a(self):
self.a.go()
def method_ab(self):
super().method_ab()
self.a.go()
class B(Base):
def __init__(self, something):
super().__init__(something)
self.b = X(something)
def method_b(self):
self.b.go()
def method_ab(self):
super().method_ab()
self.b.go()
class C(A, B):
pass
Related
I want to use a variable from class A for some computation in class B. I,m not sure that I use the self.out from the class A in class B appropriately?
Class A:
class A(nn.Module):
def __init__(self):
super(A, self).__init__()
self.out = func()
Class B:
class B(nn.Module):
def __init__(self):
super(A, self).__init__()
self.result = function_1() + A.self.out
Maybe this is what you need. I made a small example of what I understood.
These "prints" were placed to improve the understanding that Class "C" can fetch any function or variable from the other parent classes.
class A():
def __init__(self):
variable = None
def test(self, number):
return f'another class {number}'
class B():
def __init__(self):
self.data = None
self.out = self.print_data(5)
def print_data(self, number):
return number
def print_elem(self):
return self.data
class C(A, B):
def __init__(self):
super().__init__()
c = C()
print(c.print_data(8))
print(c.out)
c.data = 100
print(c.print_elem())
print(c.test(3))
How to inherit all class 'A' attributes and methods, but 'b()'?
class A:
def __init__(self):
# attributes
pass
#classmethod
def b(cls):
# logic
pass
class B(A):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def b(self):
# nothing
pass
do not use this old method( if there is another way to do it ):
class B(A):
def __init__(self, attributes):
super().__init__(self, attributes)
You can reimplement b() to raise an error:
class A:
def __init__(self):
# attributes
pass
#classmethod
def b(cls):
# logic
pass
class B(A):
def __init__(self, **kwargs):
super().__init__(**kwargs)
#classmethod
def b(cls):
raise TypeError("method b is not supported in class B")
Also, if b() is a classmethod, you should probably override it as a classmethod.
Put that method in a separate class and don't inherit it.
class A:
def __init__(self):
# attributes
pass
class A1:
#classmethod
def b(cls):
# logic
pass
class B(A):
def __init__(self, **kwargs):
super().__init__(**kwargs)
Use multiple inheritance when you want that method.
class C(A,A1):
pass
Consider the following code:
class A:
def foo(self, a):
return a
def bar(self, a):
print(foo(a))
class B(A):
def foo(self, a):
return a[0]
Now calling B.bar(a) the result is print(a[0]), but what I want is print(a). More directly: I'd like that the calling of bar()in a child class uses the definition of foogiven in A even if overridden. How do i do that?
I believe this is what you are looking for:
class A(object):
def foo(self, a):
return a
def bar(self, a):
print(A.foo(self,a))
class B(A):
def foo(self, a):
return a[0]
or alternatively:
class A:
def foo(self, a):
return a
def bar(self, a):
print(self.foo(a))
class B(A):
def foo(self, a):
return super().foo(a)
This program seems to do everything by the book, yet this issue cropped up: while a base class was being init'ed a member method was called that is overriden in the derived class and assumes that the derived class has been constructed.
Is there some best practice to protect against this?
#!/usr/bin/env python3
class A:
def __init__(self):
self.ax = 1
print(self)
def __repr__(self):
return "{} ax: {}".format(self.__class__.__name__, self.ax)
class B(A):
def __init__(self):
super().__init__()
self.bx = 10
def __repr__(self):
return super().__repr__() + " bx: {}".format(self.bx)
if __name__ == "__main__":
B()
And here's the error:
AttributeError: 'B' object has no attribute 'bx'
Generally, unless you really know what you are doing, you want to call the superclass initialization after everything your class needs to do is done. Same with this example, repr is trying to print self.bx before you initialize it. If you do
class B(A):
def __init__(self):
self.bx = 10
super().__init__()
def __repr__(self):
return super().__repr__() + " bx: {}".format(self.bx)
it works as expected
Edited:
Instead of doing computation on __init__, one idea may be to do that in a factory function/classmethod.
Example instead of doing:
class A:
def __init__(self, a, b):
self.a = a
self.b = b
self.initialize()
def initialize(self):
# do some things
Do:
class A:
def __init__(self, a, b):
self.a = a
self.b = b
#classmethod
def from_a_b(cls, a, b):
instance = cls(a, b)
instance.initialize()
return instance
I have following piece of code in Python. There are two classes A2 and B2 which share functions f1() and f2(). They differ in their base classes, deriving from A and B respectively.
I can see how to generalize this in C++ using templates. But I am not sure how to do this Python.
class A2(A):
def __init__(self):
A.__init__(self)
self._Z = Z('high')
def f1(self):
return self._Z.f1()
def f2(self):
return self._Z.f2()
# ... more functions ...
class B2(B):
def __init__(self):
B.__init__(self)
self._Z = Z('low')
def f1(self):
return self._Z.f1()
def f2(self):
return self._Z.f2()
# ... more functions ...
If I understand your question, you might try a mixin class:
class Mixin(object):
def f1(self):
return self._Z.f1()
def f2(self):
return self._Z.f2()
class A2(A, Mixin):
def __init__(self):
A.__init__(self)
self._Z = Z('high')
class B2(B, Mixin):
def __init__(self):
B.__init__(self)
self._Z = Z('low')