Unterklassen von builtin-Typen

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.
Antworten
Benutzeravatar
Goswin
User
Beiträge: 361
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen

Donnerstag 19. März 2009, 12:36

Was für einen Sinn hat es, von eingebauten Typen erben zu können, wenn man deren Methoden anscheinend nicht überschreiben kann:

Code: Alles auswählen

class Kl(object): pass
class Ukl(Kl):
  def __init__(self,x,y):
    super(Ukl,self).__init__()
    print x,y
#
class Utuple(tuple):
  def __init__(self,x,y):
    super(Utuple,self).__init__()
    print x,y
#
#
ukl = Ukl(5,6) #ok
print ukl
print
utuple = Utuple(5,6) #fehler
print utuple
Ich möchte gerne Paare anhand von zwei Argumenten definieren, aber zwei Argumente werden anscheinend grundsätzlich abgelehnt, nur weil ich von tuple erbe:

Code: Alles auswählen

class Paar(tuple):
  def __init__(self,x,y): #FALSCH
    super(Paar,self).__init__((x,y))
Kann man das irgendwie umgehen?
lunar

Donnerstag 19. März 2009, 12:42

"tuple.__new__()" überschreiben ...
DasIch
User
Beiträge: 2452
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Donnerstag 19. März 2009, 14:59

Unveränderliche Typen wie Strings, Zahlen, Tulpel usw. verwenden __new__ statt __init__.
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Donnerstag 19. März 2009, 18:02

__new__ konstruiert ein Objekt, __init__ initialisiert ein von __new__ konstruiertes Objekt. type.__call__ ruft zuerst __new__ auf, dann __init__. Die Metaklasse von tuple ist type, also wird auch tuple.__init__ aufgerufen.
Benutzeravatar
Goswin
User
Beiträge: 361
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen

Freitag 20. März 2009, 08:31

Ich mache hier offenbar etwas falsch:

Code: Alles auswählen

class Paar(tuple):
  def __new__(Paar,x,y): return tuple((x,y))
  def __str__(self): return "P(%i,%i)"%self
#
paar = Paar(2,3)
print type(paar), "isinstance(%s, Paar)==%s"%(paar,isinstance(paar,Paar))
Das erzeugte Objekt soll zwar von tuple erben, aber trotzdem type Paar haben, ich will es ja abändern können. Ein in Paar definiertes __init__ von Paar würde garnicht erst aufgerufen.
Bei

Code: Alles auswählen

class Paar(tuple):
  def __new__(cls,x,y): return cls((x,y))
  def __str__(self): return "P(%i,%i)"%self
#
paar = Paar(2,3)
print type(paar), "isinstance(%s, Paar)==%s"%(paar,isinstance(paar,Paar))
wird ein Fehler gemeldet ( __new__() takes exactly 3 arguments, 2 given).
BlackJack

Freitag 20. März 2009, 08:45

Du gibst ein `tuple` zurück und kein `Paar`-Exemplar. Ist ja klar dass das dann auch vom Typ `tuple` ist. Hast Du die Dokumentation zu `__new__()` gelesen!?

Code: Alles auswählen

In [486]: class Pair(tuple):
   .....:     def __new__(cls, x, y):
   .....:         return tuple.__new__(cls, (x, y))
   .....:     def __repr__(self):
   .....:         return 'Pair(%r, %r)' % (self[0], self[1])
   .....:

In [487]: p = Pair('answer', 42)

In [488]: p
Out[488]: Pair('answer', 42)

In [489]: type(p)
Out[489]: <class '__main__.Pair'>
Benutzeravatar
Goswin
User
Beiträge: 361
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen

Freitag 20. März 2009, 10:48

Vielen Dank; jetzt klappt es anscheinend und ich mache mal so weiter.
BlackJack hat geschrieben:Hast Du die Dokumentation zu `__new__()` gelesen?
Ich habe in meinen Pythonbüchern (u.a. Python in a nutshell, 2006) die Dokumentation zu __new__() verschiedene Male gelesen, 2_Stunden damit herumprobiert, den gestrigen Abend bis spät darüber nachgedacht, und heute früh noch einmal überprüft, ob sich nicht irgendwo ein Syntaxfehler eingeschlichen hat. Aber das alles bedeutet natürlich nicht, dass ich die Funktionsweise von __new__() richtig verstanden habe.

Die Online-Dokumentation von __new__() hatte ich nicht eingesehen (mache ich in Zukunft auch), aber ob mir damit weitergeholfen wäre, ist eine andere Frage. Online ist von der Methode "object.__new__()" die Rede; und was ich gebraucht hätte ist die Dokumentation von "tuple.__new__()" und nicht die erstere.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Freitag 20. März 2009, 11:01

``tuple`` ist eine Kindklasse von ``object``, somit gilt das ganz genauso.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Antworten