how to dynamically create an instance of a class in python?

后端 未结 7 1600
我寻月下人不归
我寻月下人不归 2020-12-01 06:09

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         


        
相关标签:
7条回答
  • 2020-12-01 06:34

    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)
    
    0 讨论(0)
  • 2020-12-01 06:35

    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()
    
    0 讨论(0)
  • 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()
    
    0 讨论(0)
  • 2020-12-01 06:41

    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.

    0 讨论(0)
  • 2020-12-01 06:42

    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.

    0 讨论(0)
  • 2020-12-01 06:49

    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

    0 讨论(0)
提交回复
热议问题