当前位置:  开发笔记 > 编程语言 > 正文

你能用字符串实例化一个类吗?

如何解决《你能用字符串实例化一个类吗?》经验,为你挑选了4个好方法。

我正在使用构建器模式来分离一堆不同的配置可能性.基本上,我有一堆名为ID的类(类似于ID12345).这些都继承自基础构建器类.在我的脚本中,每次运行此应用程序时,我都需要为每个类(大约50个)实例化一个实例.所以,我试图看看是否代替做这样的事情:

ProcessDirector = ProcessDirector()
ID12345 = ID12345()
ID01234 = ID01234()

ProcessDirector.construct(ID12345)
ProcessDirector.construct(ID01234)

ID12345.run()
ID01234.run()

我可以做这样的事情(我知道这不起作用):

IDS = ["ID12345", "ID01234"]

ProcessDirector = ProcessDirector()
for id in IDS:
  builder = id() #some how instantiate class from string
  ProcessDirector.construct(builder)
  builder.run()

这样,当我需要在将来添加一个新的时,我所要做的就是将ID添加到IDS列表中,而不是在整个代码中添加新的ID.

编辑

看起来根据数据的来源,有一些不同的意见.这些ID输入到其他人无法访问的文件中.我不是从命令行读取字符串,并且我希望将来在添加新ID时能够进行少量更改.



1> GoldenBoy..:

如果你想避免使用eval(),你可以这样做:

id = "1234asdf"
constructor = globals()[id]
instance = constructor()

前提是该类在当前范围内定义(或导入).


还是(globals()[classname_string]()`还是仅以类名作为字符串实例化对象的好方法?仍然是因为我是在最初答复后近8年问这个问题的。

2> dbr..:

不确定这是你想要的,但它似乎是一种更加Pythonic的方式来实例化字符串中列出的一堆类:

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>]


但是如果在运行之前你不知道类名是什么呢?如果从文件或命令行读取它们会怎样?
@RyanN不确定你的意思 - "IDS"列表只是一个例子,它可以来自任何地方(文件等)

3> Ignacio Vazq..:

eval()如果你能提供帮助,切勿使用.Python有这么多更好的选择(调度字典,getattr()等等),你不应该使用被称为安全漏洞eval().


我读"永远"的意思是"不惜一切代价避免,除非你完全确定你需要什么,你知道你在做什么".使用"从不"这个词虽然是一个很好的短暂选择,因为它会吓到那些不知道他们正在做什么的人.那些做的人,无论如何都会知道何时忽略这一点.
-1:"从不"太强大了.除非您也有恶意用户访问配置文件,否则这不是安全漏洞.防止恶意用户触摸配置文件很容易.
如果没有实际显示任何替代方案,这个答案实际上并没有用

4> nosklo..:

最简单的方法就是创建一个字典.

class A(object): 
    pass
class B(object): 
    pass

namedclass = {'ID12345': A, 'ID2': A, 'B': B, 'AnotherB': B,  'ID01234': B}

然后使用它(您的代码示例):

IDS = ["ID12345", "ID01234"]

ProcessDirector = ProcessDirector()
for id in IDS:
    builder = namedclass[id]() 
    ProcessDirector.construct(builder)
    builder.run()

推荐阅读
放ch养奶牛
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有