0

Let's say I want to have an object that instantiates classes depending on the input and returns it when called.

from pets import Dog, Cat

class PetCreator:
  @classmethod
  def __call__(cls, pet_type):
    if pet_type == "cat": return Cat()
    elif pet_type == "dog": return Dog()
    else: raise SomeError

def pet_creator(pet_type):
  if pet_type == "cat": return Cat()
  elif pet_type == "dog": return Dog()
  else: raise SomeError

if __name__ == "__main__":
  fav_pet_type = input() # "cat"
  my_cat = pet_creator(fav_pet_type) #this?
  my_cat = PetCreator(fav_pet_type) #or that?

Which design is more pythonic? And why would you choose one over the other

  • 1
    `PetCreator(fav_pet_type)` won't call the `__call__` class method, it'll call `object.__init__` and fail with `TypeError: object() takes no parameters ` so I'd stick with the one that works. – jonrsharpe Jun 10 '18 at 12:37
  • 1
    Possible duplicate of [What's an example use case for a Python classmethod?](https://stackoverflow.com/questions/5738470/whats-an-example-use-case-for-a-python-classmethod) – hoefling Jun 10 '18 at 12:38

1 Answers1

0

Factory objects are not ofter considered very pythonic; faced with such a problem, first class objects, methods, or functions are usually a better approach:

class Pet:
    pass

class Cat(Pet):
    pass

class Dog(Pet):
    pass

pets = {'cat': Cat, 'dog': Dog}

if __name__ == "__main__":
    pet = input()
    my_pet = pets[pet]()

Sometimes, an API will provide a set of constructors via factories whose name starts with from_...

def from_pet_name(pet: str)-> Pet:
    return pets[pet]()
Reblochon Masque
  • 35,405
  • 10
  • 55
  • 80