Langweilige Methodenüberschreibung

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
Goswin
User
Beiträge: 361
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen

Donnerstag 2. April 2009, 14:18

Ich schreibe manchmal etwas in der folgender Art:

Code: Alles auswählen

class Sonderzahl(int):
  def __new__(cls,zahl=0):
    return  super(Sonderzahl,cls).__new__(Sonderzahl,zahl)
  #
  #einzige wirklich abgeänderte Methode (nur ein Beispiel):
  def __str__(inst): return "S(%i)"%inst
  #
  def __add__(inst,szahl):
    assert isinstance(szahl,Sonderzahl)
    return Sonderzahl(super(Sonderzahl,inst).__add__(szahl))
  #
  def __sub__(inst,szahl):
    assert isinstance(szahl,Sonderzahl)
    return Sonderzahl(super(Sonderzahl,inst).__sub__(szahl))
  #
  ...viele_weitere_Methoden_der_Klasse_int...
Vorausgesetzt, man möchte auf die gesamte Funktionalität der Grundklasse nicht verzichten; ist es dann unvermeidlich, alle Methoden der Grundklasse zu überschreiben, nur weil man ein paar wenige abändern oder hinzufügen möchte?
Zuletzt geändert von Goswin am Donnerstag 2. April 2009, 15:28, insgesamt 1-mal geändert.
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Donnerstag 2. April 2009, 14:30

Prober mal aus, was passiert, wenn man nur eine Methode überschreibt :wink: Trau dich doch einfach mal, was soll schon schlimmes passieren?
Benutzeravatar
Goswin
User
Beiträge: 361
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen

Donnerstag 2. April 2009, 14:43

@derdon: Bereits geschehen. Sobald ich ein Operator oder eine Funktion für eine Sonderzahl aufrufe, ist das Ergebnis ein gewöhnliches int, und die zusätzliche Funktionalität ist futsch.

Code: Alles auswählen

assert isinstance( Sonderzahl(2)*Sonderzahl(3), Sonderzahl )
DasIch
User
Beiträge: 2452
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Donnerstag 2. April 2009, 14:49

Modifiziere dass Verhalten doch einfach über __getattr__ (nicht zu verwechseln mit __getattribute__ welches man nicht so einfach überschreiben sollte es sei den man weiß wirklich was man tut).
EyDu
User
Beiträge: 4871
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Donnerstag 2. April 2009, 14:52

Das was du willst ist eher ein Adapter und keine Vererbung. Das lässt sich recht einfach über Metaklassen lösen.
Das Leben ist wie ein Tennisball.
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Donnerstag 2. April 2009, 14:56

DasIch hat geschrieben:Modifiziere dass Verhalten doch einfach über __getattr__ (nicht zu verwechseln mit __getattribute__ welches man nicht so einfach überschreiben sollte es sei den man weiß wirklich was man tut).
Das funktioniert nicht, weil die ganzen Methoden bei New-Style-Klassen im Typ, also der Klasse, vorhanden sein müssen.

Mit Metaklassen ginge es, siehe auch den Thread zu römischen Zahlen, den es mal hier im Forum gab.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
Benutzeravatar
Goswin
User
Beiträge: 361
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen

Freitag 3. April 2009, 08:12

OK, ich versuche einmal zu lernen, was eine Metaklasse ist :shock:. Macht euch auf Anfängerfragen gefasst, denn ich habe so einige Schwierigkeiten mit dem Sprachgebrauch der Handbücher.

Rein empirisch stelle ich zunächst einmal fest, dass bei allen meinen Objekten folgende Beziehung gilt:
type(X) == X.__class__
(1) Ist das wirklich IMMER so?
(2) Wenn ja, Ist DAS die sogenannte Metaklasse von X? *befürcht nein*

Nachdem ich mir so viel Mühe gegeben habe, die Typen von den Klassen zu trennen, werden beide nun wieder in denselben Topf geworfen :(.
EyDu
User
Beiträge: 4871
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Freitag 3. April 2009, 09:41

(1) Ja
(2) Richtig, das sind keine Metaklassen.

Such mal im Forum, wie von Trundle vorgeschlagen, nach "römischen Zahlen". Ganz am Ende des Threads sind Beispiele.
Das Leben ist wie ein Tennisball.
BlackJack

Freitag 3. April 2009, 09:50

@Goswin:

1) Nein, weil nicht jedes Objekt ein `__class__`-Attribut hat. "Classic"-Klassen zum Beispiel nicht:

Code: Alles auswählen

In [778]: class A: pass
   .....:

In [779]: A.__class__
---------------------------------------------------------------------------
<type 'exceptions.AttributeError'>        Traceback (most recent call last)

/home/bj/<ipython console> in <module>()

<type 'exceptions.AttributeError'>: class A has no attribute '__class__'
Wie hast Du Typen und Klassen denn "getrennt"? Das ist in Python im Grunde das gleiche. Mittels Klassen definiert man eigene Typen. Man kann die beiden Begriffe synonym verwenden.

Klassen sind Baupläne für Objekte. Klassen selbst sind auch Objekte. Metaklassen sind also Baupläne für Objekte vom Typ Klasse. Wenn also ein Klassenobjekt erstellt wird, für das eine Metaklasse angegeben wurde, dann bekommt diese Metaklasse die Klasse und kann sie verändern.
Benutzeravatar
Goswin
User
Beiträge: 361
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen

Montag 6. April 2009, 08:13

EyDu hat geschrieben:Das was du willst ist eher ein Adapter und keine Vererbung.
...
Such mal im Forum, wie von Trundle vorgeschlagen, nach "römischen Zahlen". Ganz am Ende des Threads sind Beispiele.
Meinst du folgenden Beitrag?
http://svn.berlios.de/viewcvs/docutils/ ... iew=markup
Meinst du vielleicht, ich sollte nicht vorschnell eine Klasse definieren, sondern eher eine Funktion, damit wäre mir besser gedient? Es muss ja nicht unbedingt eine Klasse sein.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Montag 6. April 2009, 08:41

Nein, eher nicht, denn du solltest dir ein Beispiel mit Metaklassen ansehen und das was du rausgeholt hast nutzt doch nichteinmal Klassen, also wie soll das gehen, dass man darueber lernt wie Metaklassen funktionieren?
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
Goswin
User
Beiträge: 361
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen

Montag 6. April 2009, 10:11

BlackJack hat geschrieben:Wie hast Du Typen und Klassen denn "getrennt"? Das ist in Python im Grunde das gleiche. Mittels Klassen definiert man eigene Typen. Man kann die beiden Begriffe synonym verwenden.
Tja, wenn du, Blackjack, dich dafür interessierst, wie ich auf meine falschen Ideen gekommen bin, kann ich dir unter anderem "Eiffel-Erbauer" Bertrand Meyer zitieren, der meine erste objektorienterte Erfahrung verschuldet hat:
Bertrand Meyer, Object Oriented Software Construction, 2.ed.,S.166, hat geschrieben:A class is a model, and an object is an instance of such a model. This property is so obvious that it would normally deserve no comments beyond the preceeding definitions; but it has been the victim of so much confusion in the more careless segment of the literarture that we must take some time to clarify the obvious.
Alles grundsätzlich richtig, aber es entsteht der Eindruck, dass eine Klasse nie und nimmer ein Objekt ist. Wenn dann Python selber einige der Klassen "class" nennt und andere synonyme Klassen "type" nennt, dann versucht man natürlich, beides auseinanderzuhalten, und setzt voraus, dass da irgendein wichtiger Unterschied ist. Ein Unterschied scheint tatsächlich gegeben zu sein, aber ein unwichtiger: ich glaube jetzt, "type" wird eher für eingebaute Klassen (oder eingebaute Metaklassen) verwendet, und "class" eher für benutzerdefinierte Klassen (oder benutzerdefinierte Metaklassen).

Meine Hauptprobleme sind nun:

(1) Wie unterscheide ich, ob ein Objekt X eine Metaklasse ist oder nicht?
(2) Ist das "object", von dem alle anderen Klassen und sogar type erben (siehe type.__mro__), nun eine Metaklasse oder nicht?
(3) Erben Metaklassen manchmal ausschließlich von gewöhnlichen Klassen (siehe type.__mro__)?
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Montag 6. April 2009, 11:13

Goswin hat geschrieben:Alles grundsätzlich richtig, aber es entsteht der Eindruck, dass eine Klasse nie und nimmer ein Objekt ist.
Aber du solltest doch wissen, das in Python alles was an einen Namen gebunden werden kann, ein Objekt ist.
Goswin hat geschrieben:Wenn dann Python selber einige der Klassen "class" nennt und andere synonyme Klassen "type" nennt, dann versucht man natürlich, beides auseinanderzuhalten, und setzt voraus, dass da irgendein wichtiger Unterschied ist. Ein Unterschied scheint tatsächlich gegeben zu sein, aber ein unwichtiger: ich glaube jetzt, "type" wird eher für eingebaute Klassen (oder eingebaute Metaklassen) verwendet, und "class" eher für benutzerdefinierte Klassen (oder benutzerdefinierte Metaklassen).
class/type ist nur bei Old/New-Style-Klassen von Bedeutung. Erstere solltest du gar nicht nutzen, von daher kannst du sagen dass alle Metaklassen von ``type`` erben. Aber das Klassen Typen sind, das ist so oder so wahr (egal ob nun class/type). In Python merkt man das weniger, aber wenn man Java nimmt, wo man alle Typen deklarieren muss dann merkt man schnell dass zwischen ``int`` und ``MyClass`` kein sonderlicher Unterschied besteht (ahem, ok, schlechtes Beispiel).
Goswin hat geschrieben:(1) Wie unterscheide ich, ob ein Objekt X eine Metaklasse ist oder nicht?
Eine (New-Style) Metaklasse erbt von type, an irgendeiner Stelle der MRO.
Goswin hat geschrieben:(3) Erben Metaklassen manchmal ausschließlich von gewöhnlichen Klassen (siehe type.__mro__)?
Ich denke nicht. ``type`` hat doch in ``__mro__`` eine Metaklasse, nämlich sich selbst :)
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
Goswin
User
Beiträge: 361
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen

Montag 6. April 2009, 14:14

Leonidas hat geschrieben:Aber du solltest doch wissen, das in Python alles was an einen Namen gebunden werden kann, ein Objekt ist.
Interessante Erklärung. Im Python-Umfeld nehme ich das jetzt bis auf weiteres als Definition von Objekt.
Leonidas hat geschrieben: class/type ist nur bei Old/New-Style-Klassen von Bedeutung. Erstere solltest du gar nicht nutzen, von daher kannst du sagen, dass alle Metaklassen von ``type`` erben.
Ich benutze immer nur Newstyle-Klassen. Trotzdem lesen wir natürlich:

Code: Alles auswählen

print repr(int)  #liefert <type 'int'>
print repr(type('Kl',(),{}))  #liefert <class '__main__.Kl'>
Auch Python3-Benutzer werden also beiden Bezeichnungen begegnen.
Leonidas hat geschrieben: Eine (New-Style) Metaklasse erbt von type, an irgendeiner Stelle der MRO.
Das ist eine nützliche Beschreibung, auf die man erst einmal kommen muss, und die ich ebenfalls bis auf weiteres übernehme.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Montag 6. April 2009, 15:22

Goswin hat geschrieben:Ich benutze immer nur Newstyle-Klassen. Trotzdem lesen wir natürlich:

Code: Alles auswählen

print repr(int)  #liefert <type 'int'>
print repr(type('Kl',(),{}))  #liefert <class '__main__.Kl'>
Auch Python3-Benutzer werden also beiden Bezeichnungen begegnen.
Ja, hast recht. Aber generell sind Klassen nichts anderes als selbstdefinierte Datentypen. Dadurch sind Klassen eben erst nützlich, eben dass sie sich so in die Sprache einfügen. Es gibt Sprachen wo es einen Unterschied zwischen primitiven Typen gibt und definierten Klassen, jedoch halte ich das für eine schlechte Idee die zu mehr Verwirrung führt als nötig. Aber selbst dort fungieren Klassen auch als Typen.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Antworten