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'))