我想在运行时在 python 中动态创建类。
例如,我想复制下面的代码:
>>> class RefObj(object):
... def __init__(self, ParentClassName):
... print "Created RefObj with ties to %s" % ParentClassName
... class Foo1(object):
... ref_obj = RefObj("Foo1")
... class Foo2(object):
... ref_obj = RefObj("Foo2")
...
Created RefObj with ties to Foo1
Created RefObj with ties to Foo2
>>>
...但我希望动态创建 Foo1、Foo2、Foo 类(即:在执行期间而不是在首次编译时)。
实现此目的的一种方法是使用type()
,如下所示:
>>> class RefObj(object):
... def __init__(self, ParentClassName):
... print "Created RefObj with ties to %s" % ParentClassName
... def make_foo_class(index):
... name = "Foo%s" % index
... return type(name, (object, ), dict(ref_obj = RefObj(name)))
...
>>> Foo1 = make_foo_class(1)
Created RefObj with ties to Foo1
>>> Foo2 = make_foo_class(2)
Created RefObj with ties to Foo2
>>> type(Foo1()), type(Foo2())
(<class 'Foo1'>, <class 'Foo2'>)
我也可以用 来实现它exec
,如下所示:
>>> class RefObj(object):
... def __init__(self, ParentClassName):
... print "Created RefObj with ties to %s" % ParentClassName
... def make_foo_object(index):
... class_template = """class Foo%(index)d(object):
... ref_obj = RefObj("Foo%(index)d")
... """ % dict(index = index)
... global RefObj
... namespace = dict(RefObj = RefObj)
... exec class_template in namespace
... return namespace["Foo%d" % index]
...
>>> Foo1 = make_foo_object(1)
Created RefObj with ties to Foo1
>>> Foo2 = make_foo_object(2)
Created RefObj with ties to Foo2
>>> type(Foo1()), type(Foo2())
(<class 'Foo1'>, <class 'Foo2'>)
的使用exec
并不适合我(正如我所期望的那样,很多阅读此问题的人都不会使用),但这正是exec
python类的实现方式(参见这一行)。同样非常相关的是类的创建者(Raymond Hettinger)对here的这种使用的辩护。在这个辩护中,声明“命名元组的一个关键特征是它们完全等同于手写类”,这可能意味着使用不如使用...collections.namedtuple()
exec
type()
exec
有区别吗?为什么使用exec
vs type()
?
我希望答案可能是两种方式都是相同的,只是namedtuple
实现中有很多 namedtuple 变量贯穿其中,并且通过为所有方法动态生成闭包来执行此操作会使代码变得笨拙,但我想知道如果还有更多的东西。
关于我对 的不适exec
,我确实认识到,如果不受信任的各方无法向其中注入恶意代码,那应该没问题……只是确保这让我感到紧张。