我想在python中運行時動態創建類。在運行時創建類時,使用`exec'比type()`有什麼優勢?
例如,我想複製代碼如下:
>>> 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,富類(即:執行第一上通期間,而不是編譯)。實現這一
一種方法是用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的collections.namedtuple()
類is implemented(見this line)。由這個班級的創造者(Raymond Hettinger)來保護這種使用也是非常重要的。在這個辯護中,陳述「這是命名元組的一個關鍵特徵,它們完全等價於手寫類」,人們可能會認爲type()
的使用不如使用exec
...
是否有區別?爲什麼使用exec
vs type()
?
我希望答案可能是這兩個方面是相同的,它很簡單,就是namedtuple
實施有很多通過它穿插namedtuple變量,並用這樣動態生成關閉了所有的方法使代碼得到笨拙,但我想知道是否還有更多的東西。
關於我對exec
的不適感,我確實認識到,如果沒有任何方法讓不信任的人向其注入惡意代碼,那應該沒問題......它只是確保這讓我感到緊張。
關於這個問題在http://blog.ccpgames.com/kristjan/2011/05/28/namedtuple-and-exec/上有一些很好的討論,並且還有一篇關於它的好博客文章我現在沒有看到。你沒有提出任何理由,爲什麼'type'在你的情況下是有問題的,所以我不知道你爲什麼會用'exec'來打擾你,因爲你知道'type'工作。 (顯然除了好奇)。 – agf
@agf - 很棒的鏈接,謝謝!我原本沒有'type'的問題,因爲這兩種方法都有效。我只是對差異感到好奇,並試圖理解在'namedtuple'中使用'exec'的原因。提出的類/函數簽名參數是非常好的,但是...我經常遇到需要使用[裝飾器](http://pypi.python.org/pypi/decorator)包的修飾器問題。 – Russ
您能否給出動態類創建需求背後的原因還是僅僅是好奇心? – dhill