I am inheriting from a 3rd party class and want to change the default value on one of the class's methods. I can think of a few ways of doing this, but none feel clean.
So, if the base class is
class Base:
def foo(self, a=1, b=2, c=3):
return a, b, c
I want a class MyClass(Base) where b defaults to 7 instead. So,
my_obj = MyClass()
my_obj.foo() # (1, 7, 3)
my_obj.foo(b=5) # (1, 5, 3)
my_obj.foo(2, 4) # (2, 4, 3)
my_obj.foo(8) # (8, 7, 3)
I've been able to achieve the desired behavior by manually modifying args and kwargs, but it doesn't feel clean:
class OptionOne(Base):
def foo(self, *args, **kwargs):
# b is the second argument, so it is an arg if and only if there are 2 or more args
if len(args) < 2:
# If b wasn't passed as an arg, update kwargs to default b to 7.
kwargs['b'] = kwargs.get('b', 7)
return super().foo(*args, **kwargs)
Try/excepting a type error seems a little neater, but it isn't that readable:
class OptionTwo(Base):
def foo(self, *args, **kwargs):
try:
return super().foo(b=7, *args, **kwargs)
except TypeError:
# If b was already specified (as an arg or kwarg)
# "TypeError: foo() got multiple values for keyword argument 'b'"
# will be raised, so we don't override b in this case.
return super().foo(*args, **kwargs)
Is there a cleaner way of doing this that I am missing?