Virtuelle methoden in Python?
- Rebecca
- User
- Beiträge: 1662
- Registriert: Freitag 3. Februar 2006, 12:28
- Wohnort: DN, Heimat: HB
- Kontaktdaten:
Du kannst die Methode einen NotImplementedError werfen lassen.
Offizielles Python-Tutorial (Deutsche Version)
Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Mit Abstact Base Classes erreichst du wohl am ehesten was du willst.
Danke! Hier die erste Implementation die den Vorschlag von Rebecca umsetzt:
Leider komm ich nicht an den Namen der Klasse ran, wo die virtuelle Methode de facto noch nicht implementiert ist.
Code: Alles auswählen
class virtualmethod(object):
def __init__(self, func):
assert callable(func)
self._func = func
def __call__(self, *args, **kwargs):
msg = "Invalid call of %s (virtual method)." % self._func.__name__
raise NotImplementedError(msg) # --- verbessert
class VirtualDraw(object):
@virtualmethod
def draw(self):
pass
#draw = virtualmethod(draw) --- verbessert durch Dekorator
class ImplementedDraw(VirtualDraw):
def draw(self):
print "WORKS!"
test1 = VirtualDraw()
#test1 = ImplementedDraw()
test1.draw()
Zuletzt geändert von madfrog am Mittwoch 21. Januar 2009, 16:42, insgesamt 1-mal geändert.
Was spricht gegen
?
Außerdem würde man statt
Außerdem Pythons Dekoratoren kennst du?
Code: Alles auswählen
class VirtualDraw(object):
def draw(self):
raise NotImplementedError
Außerdem würde man statt
Code: Alles auswählen
raise NotImplementedError, 'my cool message'
# folgendes machen
raise NotImplementedError('my cool message')
Ich würde sagen im Sinne von Erweiterungen macht es Sinn flexibler auf solche Situationen reagieren zu könnnen, oder? So finde ich ja vielleicht noch nen Weg die Klasse rauszukriegen dessen virtuelle Methode aufgerufen wurde. Dann weiß ich besser wo ich schauen muß.DasIch hat geschrieben:Was spricht gegen?Code: Alles auswählen
class VirtualDraw(object): def draw(self): raise NotImplementedError
Ja das ändere ich. Bin noch nicht so weit was Python angeht.DasIch hat geschrieben: Außerdem würde man stattCode: Alles auswählen
raise NotImplementedError, 'my cool message' # folgendes machen raise NotImplementedError('my cool message')
Und das ist auch ein guter Tip. Dekoratoren habe ich gerade im abc Modul kennengelernt.DasIch hat geschrieben:Außerdem Pythons Dekoratoren kennst du?
Hier die zweite Umsetzung mit abc:
Code: Alles auswählen
from abc import ABCMeta, abstractmethod
class VirtualDraw(object):
__metaclass__ = ABCMeta
@abstractmethod
def draw(self):
pass
class ImplementedDraw(VirtualDraw):
def draw(self):
print "WORKS!"
test1 = VirtualDraw()
#test1 = ImplementedDraw()
test1.draw()
Kann mir noch wer sagen, wie Python den Aufruf der Klassenmethode genau aufruft? Wird bei instanz.funktion() direkt Klasse.funktion.__call__(instanz) aufgerufen oder passiert da mehr?
Da Pyton zur Kompilierzeit keine Informationen über die Datenstrukturen hat kann Klasse.funktion im Allgemeinen nicht direkt aufgerufen werden. Es wird also zunächst ein ``gettattr(instanz, "funktion")`` ausgeführt, das im Falle einer Methode eine "bound method" zurückgibt(sowas wie ``functools.partial(Klasse.funktion, instanz)``. Diese wird dann wie eine normale Funktion aufgerufen.madfrog hat geschrieben:Kann mir noch wer sagen, wie Python den Aufruf der Klassenmethode genau aufruft? Wird bei instanz.funktion() direkt Klasse.funktion.__call__(instanz) aufgerufen oder passiert da mehr?
Wenn du dich für solche Internas interessierst, hilft dir vielleicht das Modul "dis" weiter.
Code: Alles auswählen
In [46]: def foo(): return instanz.funktion()
....:
In [47]: dis.dis(foo)
1 0 LOAD_GLOBAL 0 (instanz)
3 LOAD_ATTR 1 (funktion)
6 CALL_FUNCTION 0
9 RETURN_VALUE