如何在 python 中动态创建类的实例?

我有一个类名列表,想动态地创建它们的实例。例如:

names=[
'foo.baa.a',
'foo.daa.c',
'foo.AA',
....
]


def save(cName, argument):
aa = create_instance(cName) # how to do it?
aa.save(argument)


save(random_from(names), arg)

如何在 Python 中动态创建该实例? 谢谢!

136002 次浏览

可以使用 python 内置的 eval()语句来实例化类。 像这样:

aa = eval(cName)()

注意!

使用 eval 是危险的,并且是基于代码注入的许多安全风险的关键。

这通常被称为反思,有时也称为自省。看看一些类似的问题,这些问题可以回答你正在尝试做的事情:

Python 是否等价于 Java 类 forname

可以使用字符串在 Python 中实例化类吗

通常可以完全避免字符串处理部分。

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)

注意,我们不使用类名的字符串表示形式。

在 Python 中,您可以只使用类本身。

假设您已经导入了相关的类

from [app].models import *

你需要做的就是

klass = globals()["class_name"]
instance = klass()

这对我很有效:

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)

我找到的最佳答案是: 更好的方法是做一本字典: 对象 = {} Names = [ object1,object2,object3]

对于 Names 中的 objecname: Object [ objecname ] = classname ()

发现地: Https://www.thecodingforums.com/threads/create-object-name-from-string-value.712461/

我的问题是,我希望将参数传递到 __init__,并在命令行的字符串中指定参数。例如,相当于

import a.b.ClassB as ClassB
instance = ClassB.ClassB('World')

命令行上的字符串是 "a.b.ClassB.ClassB('World')"

使用模块 a.b. ClassB 中的以下类

class ClassB():


def __init__(self, name:str):
self._name = name


def hello(self):
print("Hello " + self._name + "!")

我们可以用以下方法创建这个类

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()