Reputation: 1294
I have a parent class:
class BaseClass:
def __init__(self, foo, bar=10):
self.foo = foo
And an inherited class from it:
class InheritedClass(BaseClass):
def __init__(self, x, y, bar=10):
super().__init__(True, bar=bar)
self.x = x
self.y = y
At the moment, bar
has a default value in both the parent and the inherited class, which I have to keep track of to make sure they are both synced. How can I change the InheritedClass
constructor to instead use the default value for bar
defined in the BaseClass
?
I've tried:
class InheritedClass(BaseClass):
def __init__(self, x, y, bar=None):
if bar is None:
super().__init__(True)
else:
super().__init__(True,bar)
self.x = x
self.y = y
which provides the behavior I'm looking for, but doesn't seem very scalable. Is there a better way?
Upvotes: 2
Views: 1180
Reputation: 531165
Don't expose the parent's arguments at all in the signature; just pass what you receive on (if anything) on to the next class in the MRO.
class BaseClass:
def __init__(self, foo, bar=10, **kwargs):
super().__init__(**kwargs)
# Do something with bar
self.foo = foo
class InheritedClass(BaseClass):
def __init__(self, x, y, **kwargs)
kwargs['foo'] = True
super().__init__(**kwargs)
self.x = x
self.y = y
You have to accept and pass on arbitrary keywords anyway to use super
properly, so you may as well do the same thing for the parent class's arguments, even though you "know" them already.
This also means always using keyword arguments for __init__
, as you can't really predict how your class's positional arguments will interact with another class on the MRO. (Positional arguments can only be consumed on a first-come, first-served basis, and you simply don't know in the case of multiple inheritance when your class's method will be called.)
foo = InheritedClass(bar=9, x=3, y=10)
Upvotes: 2
Reputation: 3430
Your approach is not bad and yes there is a better way to do it maybe better than mine but here is what I come up with hope this helps.
Sample:
class BaseClass:
def __init__(self, foo, bar=10):
self.foo = foo
self.bar = bar
class InheritedClass(BaseClass):
def __init__(self, x, y, bar=None):
super().__init__(True, bar=bar)
if bar is None: bar = self.bar
self.x = x
self.y = y
Upvotes: 0
Reputation: 106553
You can use variable arguments instead:
class InheritedClass(BaseClass):
def __init__(self, x, y, *args, **kwargs):
super().__init__(True, *args, **kwargs)
self.x = x
self.y = y
Upvotes: 1