Home > Software design >  Python - How to dynamically get the class instance and return type
Python - How to dynamically get the class instance and return type

Time:10-03

Currently, I have below Python inherited class structure and created the small factory class to get the instance of the child class as below.

Here I wanted suggestions

  1. Is this a good approach or any better way to implement this?
  2. Inside the PersonFacotry class in create method, as of now, I am setting the return type as Any, Is it possible to dynamically return the type as Engineer or Doctor ?

from typing import Any

class Person:pass

class Engineer(Person):pass

class Doctor(Person):pass

class_mapper = {
    'engineer': Engineer,
    'doctor': Doctor
}

class PersonFactory:
    def create(cls, type: str) -> Any:
        return class_mapper[type]

doctor_instance = PersonFactory().create('doctor')
engineer_instance = PersonFactory().create('engineer')

Thanks a lot in advance!!

CodePudding user response:

In my opinion, this is actually a good approach. In fact, it is very readable and quickly comprehensible!
And yes, you can substitute Any with Person:

class PersonFactory:
    def create(cls, type: str) -> Person:
        return class_mapper[type]

CodePudding user response:

to recap:

code 1:

from typing import Any

class Person:pass

class Engineer(Person):pass

class Doctor(Person):pass


doctor_instance = Doctor()
engineer_instance = Engineer()

print(doctor_instance,type(doctor_instance), type(doctor_instance).__bases__)

print(engineer_instance, type(engineer_instance), type(engineer_instance).__bases__)


output:

<__main__.Doctor object at 0x7f28eedeb4c0> <class '__main__.Doctor'> (<class '__main__.Person'>,)
<__main__.Engineer object at 0x7f28eecf6d90> <class '__main__.Engineer'> (<class '__main__.Person'>,)

code 2:

from typing import Any

class Person:pass

class Engineer(Person):pass

class Doctor(Person):pass

class_mapper = {
    'engineer': Engineer(),
    'doctor': Doctor()
}

class PersonFactory:
    def create(cls, tipo: str) -> Any:
        return class_mapper[tipo]

doctor_instance = PersonFactory().create('doctor')
engineer_instance = PersonFactory().create('engineer')

print(doctor_instance, type(doctor_instance), type(doctor_instance).__bases__)

print(engineer_instance, type(engineer_instance), type(engineer_instance).__bases__)

output:

<__main__.Doctor object at 0x7fc622bfdd90> <class '__main__.Doctor'> (<class '__main__.Person'>,)
<__main__.Engineer object at 0x7fc622cf24c0> <class '__main__.Engineer'> (<class '__main__.Person'>,)

code 2 works commenting out from typing import Any and changing

def create(cls, tipo: str) -> Any: to def create(cls, tipo: str) -> Person:

Needed to change class_mapper from:

class_mapper = {
    'engineer': Engineer,
    'doctor': Doctor
}

to:

class_mapper = {
    'engineer': Engineer(),
    'doctor': Doctor()
}

as in comment to question change cls to self

  • Related