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.
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.
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.
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>]
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()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With