Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在python中动态创建类的实例?_Python - Fatal编程技术网

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

如何在python中动态创建类的实例?,python,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中动态创建该实例?谢谢 您可以使用python内置的eval()语句来实例化类。 像

我有类名列表,希望动态创建它们的实例。例如:

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中动态创建该实例?谢谢

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

aa = eval(cName)()
注意


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

这通常被称为反射或有时是内省。查看一个类似的问题,这些问题都有你想要做的事情的答案:


您通常可以完全避免使用字符串处理部分

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)
我找到的最佳答案是: 更好的方法是编一本字典: 对象={} 名称=[object1、object2、object3]

对于名称中的objname: 对象[objname]=classname()

位于:

我的问题是我想将参数传递到
\uuuu init\uuuu
,参数在命令行的字符串中指定。例如,相当于

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

其中一些示例使用了
\uuuuuuuuuuuuuuuuuuuuuuuuu
,对于较新的代码,您可以切换到
importlib
。(py>=2.7 |>=3.1)不要使用链接,请提供真实的描述。不要使用eval,因为它容易受到安全问题的影响。它是如何受到影响的?取决于上下文,如果
cName
来自用户的一些输入,这是危险的,因为黑客可以在那里注入Python代码:这是真的,但是,很多时候,您只需要使用它来从仅由开发人员/管理员控制的文本文件或环境变量设置应用程序,在这种情况下,它足够安全且简单。即使不使用
eval
,安全问题仍然存在,因为攻击者可以实例化他想要的任何类。我的观点是:应该进一步分析这个实现需求以确保安全。假设数组来自数据库。所以这个解决方案没有帮助。你只需要做
type(cName)(**arguments)
漂亮的答案。你为什么把它命名为
klass
?这个词有特殊含义吗?与django一起使用models@Nyxynyx查看“保留字”的编程概念;您通常希望避免使用在您使用的语言和库中通常用作对象和函数名的字,以便更深入地理解这里的假设。。。这要求类已经存在,而我想用动态名称定义一个新类,这对我来说非常好!非常感谢。是的,使用importlib解析类比使用反模式(如星导入)手动处理类要好得多。从Python3.3开始,这个答案是最好的解决方案。