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?
CodePudding user response:
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'))