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')
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
I am importing several classes from a library with a common method, like
class BarClass1:
def __init__(self):
pass
def bar(self, x):
return x + 1
class BarClass2:
def __init__(self):
pass
def bar(self, x):
return x + 2
class BarClass3:
def __init__(self):
pass
def bar(self, x):
return x + 3
I want to add logging to the bar method of each class, and for that purpose I create children for these classes in the following way:
def log_something(x):
print(f'input is {x}')
class DerivedBarClass1(BarClass1):
def __init__(self):
super().__init__()
def bar(self, x):
log_something(x)
return super().bar()
class DerivedBarClass2(BarClass2):
def __init__(self):
super().__init__()
def bar(self, x):
log_something(x)
return super().bar()
class DerivedBarClass3(BarClass3):
def __init__(self):
super().__init__()
def bar(self, x):
log_something(x)
return super().bar()
I feel I am doing a lot of code repetition, is there a simpler way of doing this? My main constraint is not being able to modify the code in BarClass1, BarClass2 or BarClass3.
If you can't modify the code, you can always monkey-patch the classes...
import functools
def add_logging_single_arg(f): # maybe a better name...
#functools.wraps(f)
def wrapper(self, x):
log_something(x)
return f(x)
return wrapper
for klass in [BarClass1, BarClass2, BarClass3]:
klass.bar = add_logging_single_arg(bar)
I can't seem to find information regarding what I'm trying to do, so I'm afraid the answer is "you can't do it" or "that's bad practice." But, here it goes:
Given the following:
Class A(object):
def __init__(self):
pass
def methoda(self):
return 1
Class C(object):
def __init__(self):
pass
def methodc(self):
return 2
import A, C
Class B(object):
def __init__(self, classC):
A.__init__(self)
if classC:
C.__init__(self)
def methodb(self):
return 2
Obviously, running:
b = A()
b.methoda()
Is going to crash with an error:
Unbound method __init()___ must be called with A class as first argument (got B instance instead)
However, I am basically looking for a way to make this work. My motivation:
There are classes (maybe in the future) that will duplicate a certain group of methods (say some fancy conversions). In an effort to reduce code, I'd like for the future classes to inherit the methods; but for legacy reasons, I don't want B to inherit C.
A couple solutions:
Don't use special methods directly:
class A(object):
def __init__(self):
self._init(self)
#staticmethod
def _init(self):
...actual initialization code here...
def methoda(self):
return 1
class C(object):
def __init__(self):
self._init(self)
#staticmethod
def _init(self):
...actual initialization code here...
def methodc(self):
return 2
import A, C
class B(object):
def __init__(self, classC):
A._init(self)
if classC:
C._init(self)
def methodb(self):
return 2
Or silly hacks involving copying from initialized objects:
import A, C
class B(object):
def __init__(self, classC):
vars(self).update(vars(A()))
if classC:
vars(self).update(vars(C()))
def methodb(self):
return 2
Note that none of these solutions will give access to methods from A or C on instances of B. That's just ugly. If you really need inheritance, use inheritance, don't do terrible things trying to simulate it poorly.
I ended up just inheriting multiple classes. It's not exactly the way I wanted it done, but it's cleaner and easier for the IDE to follow
Class A(object):
def __init__(self):
super(A, self).__init__()
pass
def methoda(self):
return 1
Class C(object):
def __init__(self):
super(C, self).__init__()
def _C_init(self):
# some init stuff
pass
def methodc(self):
return 1
Class B(A, C):
def __init__(self, use_C):
super(B, self).__init__()
if use_C:
self._C_init()
def methodb(self):
return 2
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