I have list of class names and want to create their instances dynamically. for example:
names=[
\'foo.baa.a\',
\'foo.daa.c\',
\'foo.AA\',
....
]
def save(c
This worked for me:
from importlib import import_module
class_str: str = 'A.B.YourClass'
try:
module_path, class_name = class_str.rsplit('.', 1)
module = import_module(module_path)
return getattr(module, class_name)
except (ImportError, AttributeError) as e:
raise ImportError(class_str)
My problem was that I wanted to pass arguments into __init__
with the arguments being specified in a string on the command line. For example, the equivalent of
import a.b.ClassB as ClassB
instance = ClassB.ClassB('World')
The string on the command line is "a.b.ClassB.ClassB('World')"
With the following class in module a.b.ClassB
class ClassB():
def __init__(self, name:str):
self._name = name
def hello(self):
print("Hello " + self._name + "!")
we can create this class with the following
import importlib
def create_instance(class_str:str):
"""
Create a class instance from a full path to a class constructor
:param class_str: module name plus '.' plus class name and optional parens with arguments for the class's
__init__() method. For example, "a.b.ClassB.ClassB('World')"
:return: an instance of the class specified.
"""
try:
if "(" in class_str:
full_class_name, args = class_name = class_str.rsplit('(', 1)
args = '(' + args
else:
full_class_name = class_str
args = ()
# Get the class object
module_path, _, class_name = full_class_name.rpartition('.')
mod = importlib.import_module(module_path)
klazz = getattr(mod, class_name)
# Alias the the class so its constructor can be called, see the following link.
# See https://www.programiz.com/python-programming/methods/built-in/eval
alias = class_name + "Alias"
instance = eval(alias + args, { alias: klazz})
return instance
except (ImportError, AttributeError) as e:
raise ImportError(class_str)
if __name__ == "__main__":
instance = create_instance("a.b.ClassB.ClassB('World')")
instance.hello()
Assuming you have already imported the relevant classes using something like
from [app].models import *
all you will need to do is
klass = globals()["class_name"]
instance = klass()
You can use the python builtin eval()
statement to instantiate your classes.
Like this:
aa = eval(cName)()
Notice!
using eval is dangerous and is a key for lots of security risks based on code injections.
You can often avoid the string processing part of this entirely.
import foo.baa
import foo.AA
import foo
classes = [ foo.baa.a, foo.daa.c, foo.AA ]
def save(theClass, argument):
aa = theClass()
aa.save(argument)
save(random.choice(classes), arg)
Note that we don't use a string representation of the name of the class.
In Python, you can just use the class itself.
This is often referred to as reflection or sometimes introspection. Check out a similar questions that have an answer for what you are trying to do:
Does Python Have An Equivalent to Java Class forname
Can You Use a String to Instantiate a Class in Python