Suppose I have a class Fruit and two Subclasses of it Orange(Fruit) and Banana(fruit)
Fruit has an initializer, and I pass some parameters to it. But I don’t want it to just create and return a fruit necessarily, but based upon the parameters passed to it, to possibly return one of several different subclasses of it. For example:
Fruit(color="yellow") might return a Banana object whereas Fruit(color="orange") would return an Orange.
How can I do this? I can’t do it in __init__ because the class has already been created. I tried doing it in __new__ but this wound up messy because my could would create the subclass (as expected), but would then wind-up recursivley calling the Superclass’s __new__.
My workaround has been to just define a Fruit.create() static method which creates the appropriate subclass, but this seems a little un-Pythonic.
Is there a “correct” way to do this?
Advertisement
Answer
My point of view is the same as Chris Doyle.
You can use factory mode or your Fruit.create(), I think they are very good
If you want to use your ideas, you can do so
class Meta(type):
def __call__(cls, *args, **kwargs):
if cls is Fruit:
color = kwargs.pop('color', None)
if color is None:
raise ValueError("missing keyword argument `color`")
match color:
case 'yellow':
return Banana()
case 'orange':
return Orange()
case _:
raise ValueError("invalid color: %s" % color)
return super().__call__(*args, **kwargs)
class Fruit(metaclass=Meta):
def __init__(self, *, color=None): # noqa
pass
class Banana(Fruit):
pass
class Orange(Fruit):
pass
if __name__ == '__main__':
print(Fruit(color='yellow'))
print(Fruit(color='orange'))