Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.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_Design Patterns_Reflection - Fatal编程技术网

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

Python 你能用一个字符串来实例化一个类吗?,python,design-patterns,reflection,Python,Design Patterns,Reflection,我正在使用一个构建器模式来分离一系列不同的配置可能性。基本上,我有一堆名为ID的类(类似于ID12345)。这些都继承自基本生成器类。在我的脚本中,每次运行这个应用程序时,我需要为每个类(大约50个)实例化一个实例。所以,我想看看,如果不是这样做: ProcessDirector = ProcessDirector() ID12345 = ID12345() ID01234 = ID01234() ProcessDirector.construct(ID12345) ProcessDirect

我正在使用一个构建器模式来分离一系列不同的配置可能性。基本上,我有一堆名为ID的类(类似于ID12345)。这些都继承自基本生成器类。在我的脚本中,每次运行这个应用程序时,我需要为每个类(大约50个)实例化一个实例。所以,我想看看,如果不是这样做:

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

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

ID12345.run()
ID01234.run()
我可以这样做吗(我知道这样不行):

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

编辑
根据数据来源,似乎有一些不同的观点。这些ID输入到其他人无权访问的文件中。我没有从命令行读取字符串,我希望在将来添加新ID时能够做尽可能少的更改

你的问题遗漏了一些东西,所以我不得不猜测遗漏的东西。请随意编辑您的问题以更正遗漏

class ProcessDirector( object ):
    # does something

class ID12345( SomeKindOfProcess ):
    pass

class ID001234( SomeKindOfProcess ):
    pass

idList= [ID12345, ID01234]

theProcessDirector = ProcessDirector()
for id in idList:
  builder = id() #Instantiate an object from the class object
  theProcessDirector.construct(builder)
  builder.run()
这个很好用。它不是从字符串实例化的——实际上,您通常不希望这样。有时,但很少。更常见的情况是,您可以创建一个类对象列表,从中获取实例对象

如果您实际上是从命令行获取类名,那么您需要做以下小的更改

validClasses = [ ID12345, ID01234 ]
validMap = dict( ( (c.__name__, c) for c in validClasses ) )
nameStrings = [ "ID12345", "ID01234" ] # from your command-line 
idList= [ validMap[s] for s in nameStrings ]
其他一切都是一样的

[此外,如果可能,请尝试以小写字母开头实例变量名称。以大写字母开头的名称通常是类名。]

编辑


已删除
eval
。尽管
eval()
绝对不是一个安全漏洞。Eval(和
exec
execfile
)只有在有人专门授予恶意用户访问权限时才会出现问题。

如果您可以帮助,请不要使用
Eval()
。Python有很多更好的选项(dispatch dictionary,
getattr()
,等等),因此您永远不必使用称为
eval()
的安全漏洞,最简单的方法就是创建一个dict

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

namedclass = {'ID12345': A, 'ID2': A, 'B': B, 'AnotherB': B,  'ID01234': B}
然后使用它(您的代码示例):


如果要避免eval(),可以执行以下操作:

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

假设类是在当前范围中定义的(或导入到当前范围中)。

不确定这是否是您想要的,但这似乎是一种更具python风格的方式来实例化字符串中列出的一组类:

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>]
class-idclass:
ID12345类:通行证
ID01234类:通行证
#也可以是:导入IDClass
班级主任:
定义初始化(自):
self.allClasses=[]
def构造(自身、构建名称):
targetClass=getattr(idClasses,builderName)
实例=targetClass()
self.allClasses.append(实例)
IDS=[“ID12345”、“ID01234”]
director=ProcessDirector()
对于id中的id:
建筑总监(id)
打印控制器.allClasses
# [, ]

我决定把a和a放在一起,我还添加了重载的
\uuu getitem\uuuu
,所以这看起来更像工厂模式

import sys
import traceback
import ipdb


class CarTypes:
    class Toyota:
        def __repr__(self):
            return "Toyota()"
        def __str__(self):
            return "Instance of Toyota() class"
    class Nissan:
        def __repr__(self):
            return "Nissan()"
        def __str__(self):
            return "Instance of Nissan() class"


class Car:
    def __init__(self):
        self._all_classes = {}

    def construct(self, builder_name):
        setattr(self, builder_name, CarTypes())
        try:
            target_class = getattr(CarTypes, builder_name)
            instance = target_class()
            self._all_classes[builder_name] = instance
        except AttributeError:
            print("Builder {} not defined.".format(builder_name))
            traceback.print_stack()

    def __getitem__(self, type_name):
        return self._all_classes[type_name]

    def car_type(self, type_name):
        return self._all_classes[type_name]


IDS = ["Toyota", "Nissan", "Unknown"]

director = Car()
for id in IDS:
    director.construct(id)

print(director["Toyota"])
print(director["Nissan"])
print(director.car_type("Toyota"))
print(director.car_type("Nissan"))
已编辑:我添加了一些错误处理


已编辑:放置在下。享受。

这些ID类与循环在同一个文件中,还是从其他地方导入?重复:这不是重复,这是一个python问题,不是java问题,您引用的问题是询问python中是否存在java中存在的函数,后面没有什么解释,请记住,问题是人们如何找到它,而不是答案。因此,仅仅因为答案存在于另一个可能回答这个问题的问题中,并不意味着人们会找到它,除非他们从java的角度思考这个问题,就像这个问题的OP一样。-1:“从不”太强了。这不是一个安全漏洞,除非您还有可以访问配置文件的恶意用户。防止恶意用户接触配置文件很容易。我把“从不”理解为“不惜一切代价避免,除非你绝对确定它是你需要的,并且你知道你在做什么”。不过,使用“从不”这个词是一个很好的简短选择,因为它会吓坏那些不知道自己在做什么的人。不管怎样,那些知道的人都知道什么时候应该忽略这个问题。如果不实际显示任何替代项,这个答案就没有什么帮助了。但是如果在运行时之前你不知道类名会是什么呢?如果它们是从文件或命令行读取的,该怎么办?@RyanN不确定您的意思-
IDS
列表只是一个例子,它可能来自任何地方(文件等),我可能忽略了一些东西,但在idClasses中,您有一个名为ID12345的类。我现在看到OP已经有了一大堆他想要实例化的类,我想到了一个被多次实例化的泛型类,比如一个类
class car():\r\n def\uu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuoSelf:pass
在construct()中实例化为['ford',toyota',vw'],你可以做
setattr(self,builderName,idClasses())
。这样,您将得到director.ford、director.toyota和director.vw对象。+1-这非常有用,只是结合
abc
动态构建基类所有子类的一个实例。is
globals()[classname_string]()
对于仅以字符串形式给出类名的对象,仍然是一种很好的实例化方法吗?仍然是因为我在最初的回答差不多8年后才提出这个问题。这是最具python风格的方式!事实上,这也是我们在python中模拟缺少的“switch语句”的方式!!这当然是一种方法,但问题并不完全在于此:它不是使用字符串来派生要实例化的类,而是它的实际类。这样做的一个缺点是
namedclass
必须位于它列出的所有类之后。Django还使用字符串来引用模型
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>]
import sys
import traceback
import ipdb


class CarTypes:
    class Toyota:
        def __repr__(self):
            return "Toyota()"
        def __str__(self):
            return "Instance of Toyota() class"
    class Nissan:
        def __repr__(self):
            return "Nissan()"
        def __str__(self):
            return "Instance of Nissan() class"


class Car:
    def __init__(self):
        self._all_classes = {}

    def construct(self, builder_name):
        setattr(self, builder_name, CarTypes())
        try:
            target_class = getattr(CarTypes, builder_name)
            instance = target_class()
            self._all_classes[builder_name] = instance
        except AttributeError:
            print("Builder {} not defined.".format(builder_name))
            traceback.print_stack()

    def __getitem__(self, type_name):
        return self._all_classes[type_name]

    def car_type(self, type_name):
        return self._all_classes[type_name]


IDS = ["Toyota", "Nissan", "Unknown"]

director = Car()
for id in IDS:
    director.construct(id)

print(director["Toyota"])
print(director["Nissan"])
print(director.car_type("Toyota"))
print(director.car_type("Nissan"))