I have legacy class hierarchy which I want to extend with new class with different method signature: overrided method should return tree values instead of two. Third return value for legacy classes should be some default value. Example below (repl.it).
class BaseClass:
def do_work(self):
param1, param2, param3 = self.get_params()
self._process(param1, param2, param3)
def get_params(self):
# this method shoud be overrided in the child class
raise NotImplementedError()
def _process(self, param1, param2, param3):
# do some process, for example, print params
print(param1, param2, param3)
class LegacyChild(BaseClass):
def get_params(self):
return 1, 2, 3
class NewChild(BaseClass):
def get_params(self):
return 1, 2
legacy_child = LegacyChild()
legacy_child.do_work()
new_child = NewChild()
new_child.do_work()
In this case I get ValueError: not enough values to unpack (expected 3, got 2)
on third line. And this is correct.
My first thought to solve this was to change hardcoded three params to tuple with variable length and then set param1
, param2
and param3
based on it's length:
class BaseClass:
def do_work(self):
params = self.get_params()
if len(params) == 3:
param1, param2, param3 = params
else:
param1, param2 = params
param3 = 3 # some default value
self._process(param1, param2, param3)
def get_params(self):
# this method shoud be overrided in the child class
raise NotImplementedError()
def _process(self, param1, param2, param3):
# do some process, for example, print params
print(param1, param2, param3)
I think that this solution is too rough (repl.it).
Is there any other possible solution for that problem?
Maybe this?
param1, param2, *param3 = self.get_params() # param3 is an array. When there are only 2 elements, it's empty.
self._process(param1, param2, (param3 or [3])[0]) # 3 is the default value
This is assuming that get_params
will always produce 2 or 3 elements. It can't be easily extended to handle methods that return only one element.