Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you use a string to instantiate a class?

I'm using a Builder pattern in Python to separate a bunch of different configuration possibilities. Basically, I have a bunch of classes that are named ID... (e.g. ID12345). These all inherit from the base Builder class. In my script, I need to instantiate an instance for each class (about 50) every time this app runs. So, I'm trying to see if instead of doing something like this:

ProcessDirector = ProcessDirector()
ID12345 = ID12345()
ID01234 = ID01234()

ProcessDirector.construct(ID12345)
ProcessDirector.construct(ID01234)

ID12345.run()
ID01234.run()

Can I do something like this (I know this doesn't work):

IDS = ["ID12345", "ID01234"]

ProcessDirector = ProcessDirector()
for id in IDS:
  builder = id() #some how instantiate class from string
  ProcessDirector.construct(builder)
  builder.run()

That way, when I need to add a new one in the future, all I have to do is add the id to the IDS list, rather than peppering the new ID throughout the code.

EDIT:

Looks like there are different opinions based on where the data is coming from. These IDs are entered in a file that no one else has access to. I'm not reading the strings from the command line, and I'd like to be able to do as little alteration when adding a new ID in the future.

like image 257
scottm Avatar asked Feb 16 '09 16:02

scottm


People also ask

How do I create an instance of a string?

If you have a class 'ReportClass' is available, you can instantiate it directly as shown below. ReportClass report = new ReportClass(); The code ReportClass report = (ReportClass)Activator. CreateInstance(Type.


3 Answers

If you wanted to avoid an eval(), you could just do:

id = "1234asdf"
constructor = globals()[id]
instance = constructor()

Provided that the class is defined in (or imported into) your current scope.

like image 146
GoldenBoy Avatar answered Oct 13 '22 08:10

GoldenBoy


Not sure this is what you want but it seems like a more Pythonic way to instantiate a bunch of classes listed in a string:

class idClasses:
    class ID12345:pass
    class ID01234:pass
# could also be: import idClasses

class ProcessDirector:
    def __init__(self):
        self.allClasses = []

    def construct(self, builderName):
        targetClass = getattr(idClasses, builderName)
        instance = targetClass()
        self.allClasses.append(instance)

IDS = ["ID12345", "ID01234"]

director = ProcessDirector()
for id in IDS:
    director.construct(id)

print director.allClasses
# [<__main__.ID12345 instance at 0x7d850>, <__main__.ID01234 instance at 0x7d918>]
like image 20
dbr Avatar answered Oct 13 '22 06:10

dbr


Never use eval() if you can help it. Python has so many better options (dispatch dictionary, getattr(), etc.) that you should never have to use the security hole known as eval().

like image 27
Ignacio Vazquez-Abrams Avatar answered Oct 13 '22 08:10

Ignacio Vazquez-Abrams