2010-02-09 82 views
16

所以我有一組類和一個類名稱的字符串。我如何基於該字符串實例化一個類?從一個名稱實例化一個Python類

class foo: 
    def __init__(self, left, right): 
    self.left = left 
    self.right = right 

str = "foo" 
x = Init(str, A, B) 

我想x是類foo的實例化。

+2

重複。 http://stackoverflow.com/questions/734970/python-reference-to-a-class-from-a-string,http://stackoverflow.com/questions/1176136/convert-string-to-python-class-對象,http://stackoverflow.com/questions/553784/can-you-use-a-string-to-instantiate-a-class-in-python等 – 2010-02-09 11:17:20

回答

13

如果您知道有關的命名空間,你可以直接使用它 - 例如,如果所有的類都是模塊zap,字典vars(zap)是命名空間;如果他們都在當前模塊中,那麼globals()可能是獲取該字典的最方便方法。

如@Ignacio所示,如果這些類不是全部在同一個命名空間中,那麼建立一個「人造」命名空間(一個專用字典,類名稱作爲鍵和作爲值的類對象)可能是最簡單的方法。

6
classdict = {'foo': foo} 

x = classdict['foo'](A, B) 
+2

我怎樣才能使用反射? – klynch 2010-02-09 02:33:36

+0

您*可以*使用'getattr()',但這可能會使您面臨安全問題。使用類裝飾器可讓您自動枚舉類,但這些類只存在於較新版本的Python中。 – 2010-02-09 02:36:07

+0

你會如何使用裝飾者?它會附加到可實例化類的列表 - 我將不得不遍歷這個列表來選擇正確的類來實例化嗎? – 2017-01-21 07:36:09

15

在你的情況,你可以使用類似

get_class = lambda x: globals()[x] 
c = get_class("foo") 

它從模塊的更容易沒有get類

import somemodule 
getattr(somemodule, "SomeClass") 
2
classname = "Foo" 
foo = vars()[classname](Bar, 0, 4) 

或許

def mkinst(cls, *args, **kwargs): 
    try: 
     return globals()[cls](*args, **kwargs) 
    except: 
     raise NameError("Class %s is not defined" % cls) 

x = mkinst("Foo", bar, 0, 4, disc="bust") 
y = mkinst("Bar", foo, batman="robin") 

上即可雜記:

*args**kwargs在Python特殊參數,他們的意思是«非關鍵字參數的數組»和«關鍵字的字典args»相應地。

PEP-8(官方Python風格指南)建議對類變量使用cls

vars()返回本地作用域中定義的變量的詞典。

globals()返回當前在局部範圍之外的環境中存在的變量的詞典。

1

你可能會考慮元類的使用量,以及:

Cls = type('foo',(), foo.__dict__) 
x = Cls(A, B) 

然而,它創建另一個同級。