RE: [python] dynamická instance třídy
Petr Prikryl
Prikryl na skil.cz
Čtvrtek Květen 5 14:04:08 CEST 2005
> Chci dynamicky vytvářet instance tříd. [...]
>
> mycls = createInstance("MyClass", args)
Základní myšlenku vyjádřil Martin Blazik. Následující
příklad ukazuje princip:
class MyClass:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def __str__(self):
return str(self.a) + ' ' + str(self.b) + ' ' + str(self.c)
class OtherClass:
def __init__(self, a):
self.a = a
def __str__(self):
return 'OtherClass instance: ' + str(self.a)
def createInstance(clsname, *args):
try:
cls = globals()[clsname]
obj = cls(*args)
return obj
except:
print 'Unknown class: ', clsname
return None
#-----------------------------------------------------
o1 = MyClass(1, 2, 3)
print o1
o2 = createInstance('MyClass', *('a', 'b', 'c'))
print o2
o3 = createInstance('OtherClass', *('x',))
print o3
o4 = createInstance('AnotherClass', *('x', 'y', 'z'))
print o4
o5 = eval('MyClass')(*(5, 6, 7))
print o5
o6 = eval('MyClass')(8, 9, 10)
print o6
cls = eval('MyClass')
o7 = cls(11, 12, 13)
print o7
===================================================
Výstup:
1 2 3
a b c
OtherClass instance: x
Unknown class: AnotherClass
None
5 6 7
8 9 10
11 12 13
===================================================
Funkce createInstance() byla nadefinována od boku.
Hledá objekt definující požadovanou třídu v globálním
slovníku -- viz globals(). Protože se obecně předpokládá
různý počet parametrů, používá speciálnější způsob
předávání parametrů sekvencí.
Použití eval není tak průhledné, ale je jednodušší
a má další (neukázané) možnosti.
Princip spočívá v nalezení interního objektu, který
reprezentuje požadovanou třídu. Přiřazením tento
objekt spojím s mnou zadaným jménem (jako u ostatních
proměnných). Voláním vzniká instance třídy. Při volání
musím předat požadované parametry.
Naznačená funkce createInstance() kombinuje
jak hledání třídy (třída je reprezentována objektem),
tak předávání parametrů. Poslední příklady (o6, o7)
ukazují lidštější způsob předávání parametrů.
Poslední příklad dělá přesně totéž, co o6. Rozdíl
spočívá jen v tom, že se objekt reprezentující třídu
nejdříve zapamatuje pod jménem cls.
Petr
P.S. Funkce apply() (první Martinovo řešení)
se již považuje za zastaralou. Pokud potřebujeme
pracovat s proměnným počtem parametrů, měla by se
používat rozšířená syntaxe pro volání funkce.
To ale nijak nesouvisí s eval().
Další informace o konferenci Python