Seite 1 von 1

Unterklassen von builtin-Typen

Verfasst: Donnerstag 19. März 2009, 12:36
von Goswin
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?

Verfasst: Donnerstag 19. März 2009, 12:42
von lunar
"tuple.__new__()" überschreiben ...

Verfasst: Donnerstag 19. März 2009, 14:59
von DasIch
Unveränderliche Typen wie Strings, Zahlen, Tulpel usw. verwenden __new__ statt __init__.

Verfasst: Donnerstag 19. März 2009, 18:02
von str1442
__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.

Verfasst: Freitag 20. März 2009, 08:31
von Goswin
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).

Verfasst: Freitag 20. März 2009, 08:45
von BlackJack
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'>

Verfasst: Freitag 20. März 2009, 10:48
von Goswin
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.

Verfasst: Freitag 20. März 2009, 11:01
von Leonidas
``tuple`` ist eine Kindklasse von ``object``, somit gilt das ganz genauso.