Reputation: 307
Suppose we have two classes and each computes a property stuff
in a different way. Is is possible to combine their outputs in a method/property of a child class?
The following code shows the desired effect (though get_stuff_from
needs to be replaced by a proper python construct, if such thing exists).
class Foo():
@property
def stuff(self):
return ['a','b','c']
class Bar():
@property
def stuff(self):
return ['1','2','3']
class FooBar(Foo, Bar):
@property
def stuff(self):
# Computes stuff from the internal state like Foo().stuff
foo_stuff = get_stuff_from(Foo)
# Computes stuff from the internal state like Bar().stuff
bar_stuff = get_stuff_from(Bar)
# Returns the combined results
return foo_stuff + bar_stuff
foo_bar = FooBar()
print(foo_bar.stuff)
which should output:
['a', 'b', 'c', '1', '2', '3']
If stuff
were a method instead of a property, this would be simple to implement:
class Foo():
def stuff(self):
return ['a','b','c']
class Bar():
def stuff(self):
return ['1','2','3']
class FooBar(Foo, Bar):
def stuff(self):
# Computes stuff from the internal state like Foo().stuff
foo_stuff = Foo.stuff(self)
# Computes stuff from the internal state like Bar().stuff
bar_stuff = Bar.stuff(self)
# Returns the combined results
return foo_stuff + bar_stuff
foo_bar = FooBar()
print(foo_bar.stuff())
however, I would like to find out whether it is possible to do the same with properties.
Upvotes: 0
Views: 122
Reputation: 530970
Having two parents using the same name for two different things is a conflict you should fix before inheriting. Usually, this means using at least one adaptor class.
class Foo():
@property
def stuff(self):
return ['a','b','c']
class Bar():
@property
def stuff(self):
return ['1','2','3']
class BarAdaptor:
def __init__(self):
self.b = Bar()
@property
def bar_stuff(self):
return self.b.stuff
class FooBar(Foo, BarAdaptor):
# Don't repeat or perpetuate the mistake of
# overloading stuff to mean different things.
@property
def foobar_stuff(self):
return self.stuff + self.bar_stuff
For symmetry, you might want to adapt Foo
and Bar
.
This is inspired by the advice for incorporating non-cooperative classes into a hierarchy of cooperative multiple inheritance classes, outlined in Python's `super() considered super!.
Upvotes: 1
Reputation: 1461
You can do this using the code below
class FooBar(Foo, Bar):
def __init__(self):
self.foo = Foo()
self.bar = Bar()
@property
def stuff(self):
return self.foo.stuff + self.bar.stuff
Upvotes: -1
Reputation: 25489
A property is just an object with an fget
method. You could access the base class' property object and invoke its fget
method with the self
object that refers to the child class:
class FooBar(Foo, Bar):
@property
def stuff(self):
# Computes stuff from the internal state like Foo().stuff
foo_stuff = Foo.stuff.fget(self)
# Computes stuff from the internal state like Bar().stuff
bar_stuff = Bar.stuff.fget(self)
# Returns the combined results
return foo_stuff + bar_stuff
And now FooBar().stuff
returns ['a', 'b', 'c', '1', '2', '3']
Upvotes: 1
Reputation: 1087
You could do it like this, otherwise I don't know why you're deriving from Foo and Bar. In your current code you were just overwriting these properties.
class Foo():
@property
def stuff(self):
return self._foo_stuff
@property
def _foo_stuff(self):
return ['a','b','c']
class Bar():
@property
def stuff(self):
return self._bar_stuff
@property
def _bar_stuff(self):
return ['1','2','3']
class FooBar(Foo, Bar):
@property
def stuff(self):
return self._foo_bar_stuff
@property
def _foo_bar_stuff(self):
return self._foo_stuff + self._bar_stuff
foo_bar = FooBar()
print(foo_bar.stuff)
Output:
['a', 'b', 'c', '1', '2', '3']
Upvotes: 0