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