I have the following class hierarchy. The goal is for the calling code to choose either a base Foo
object or a Foobar
object that also provides the additional Bar
functionality.
class Foo:
def __init__(self):
self.foo = 'foo'
class Bar:
def __init__(self, attr):
self.attr = attr
def bar(self):
print(self.attr + 'bar')
class Foobar(Foo, Bar):
def __init__(self):
super().__init__(self.foo)
But when I try to run it:
>>> fb = Foobar()
AttributeError: 'Foobar' object has no attribute 'foo'
What's the right way to initialize Foobar
? I've read a number of articles and SO posts about initialization with multiple inheritance, but none where one base constructor requires a property of the other base class.
EDIT:
My actual use case is derived from https://www.pythonguis.com/tutorials/pyside6-plotting-matplotlib/. "Bar
" is actually FigureCanvasQTAgg
and "Foobar
" corresponds to MplCanvas
. Foobar
must derive from FigureCanvasQTAgg
because the Foobar
object will be passed to a bunch of PySide6 code that uses attributes I don't know about. I'm trying to break out the regular matplotlib
code into another base class (Foo
) to I can make an alternate front end that doesn't use PySide6, but there may be a different way to achieve this goal.
EDIT 2:
Looks like the whole approach may be flawed. It would certainly be less taxing for my little brain to create foo
in a separate function before trying to instantiate either a Foo
or a Foobar
.
A demo for you(Just to tell why your Foobar does not have a attr
attribution, don't don't do it in real code):
class Foo:
def __init__(self):
self.foo = 'foo'
class Bar:
def __init__(self, attr):
self.attr = attr
def bar(self):
print(self.attr + 'bar')
class Foobar(Foo, Bar):
def __init__(self):
super().__init__() # Will use: Foo.__init__
Bar.__init__(self, self.foo)
Foobar().bar()
# foobar
I would rather do:
class Foo:
foo = "foo"
class Bar:
def __init__(self, attr) -> None:
self.attr = attr
def bar(self) -> None:
print(self.attr + "bar")
class FooBar(Foo, Bar):
def __init__(self) -> None:
super().__init__(self.foo)
FooBar().bar()
# foobar