AW: [Python-de] dynamisch Methoden aufrufen

Ulrich Berning ulrich.berning at t-online.de
Mit Nov 12 23:37:46 CET 2003


Rainer Fischbach wrote:

>Kann auch nicht gehen, da die Methoden nicht im __dict__ der Ausprägungen stehen, sondern in dem der Klasse. Dabei musst Du darauf achten, dass dort die ungebundene Methode steht, Du also die Ausprägung explizit als Parameter übergeben musst! So geht's:
>
>C.__dict__[name](c)
>  
>
Damit fällt die Vererbung dann unter den Tisch, da die Methoden der 
Superklassen nicht im __dict__ einer Klasse auftauchen. Dies gilt auch für:

getattr(c, name)(c)

Folgendes wird funktionieren:

getattr(C, name)(c)

besser wäre:

getattr(c.__class__, name)(c)

da dann nur die Instanz benötigt wird und nicht die Klasse selber. Dann 
wird's aber so langsam unleserlich.

Die sauberste Lösung ist, der (Basis-)Klasse eine Methode call_by_name 
zu verpassen, die den Aufruf der gewünschten Methode übernimmt und 
gegebenenfalls AttributeError wirft:

Beispiel:
-------------------------------------
class A:
    def one(self, *args):
        print "one called from a %s instance with:" % 
self.__class__.__name__, args

    def call_by_name(self, name, *args):
        getattr(self, name)(*args) # Innerhalb der Klasse geht's mit self
   
class B(A):
    def two(self, a, b, c):
        print "two called from a %s instance with:" % 
self.__class__.__name__, a, b, c
   
class C(B):
    def three(self):
        print "three called from a %s instance" % self.__class__.__name__
       
a = A()
b = B()
c = C()

a.call_by_name("one", "Hello", "World")

b.call_by_name("one")
b.call_by_name("two", 1, 2, 3)

c.call_by_name("one", [], None, {})
c.call_by_name("two", 4, 5, 6)
c.call_by_name("three")

try:
    c.call_by_name("four")
except AttributeError, args:
    print "Expected AtributeError:", args
-------------------------------------

Ergebnis:
-------------------------------------
one called from a A instance with: ('Hello', 'World')
one called from a B instance with: ()
two called from a B instance with: 1 2 3
one called from a C instance with: ([], None, {})
two called from a C instance with: 4 5 6
three called from a C instance
Expected AtributeError: C instance has no attribute 'four'
-------------------------------------

Ciao, Ulli