Vererbung über mehrere Instanzen

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
Malibu
User
Beiträge: 4
Registriert: Samstag 9. Juni 2007, 12:16

Hi Leute.
Für meine mündliche Prüfung in Informatik bin ich gerade am Aufarbeiten meines alten Stoffs. Zur OOM haben wir ein Projekt namens Hofzwerge bearbeitet. Da ich meinen Orginalcode leider nicht mehr habe, hab ich den von Splsah aus diesem Forum genommen und ihn überarbeitet. Ich bin dabei auf ein Problem mit der Vererbung gestoßen. Der Code:

Code: Alles auswählen

class Zwerg:
    def __init__(self):
        self.name=''
        self.werta=2       #Hierauf kommt es an
        self.wertb=4       #sowie hierauf
        self.basisfreibetrag=10
        self.steuerbetrag=3
        self.nettogehalt=0
"""
    def ausgabe(self):
        
        a=self.basisfreibetrag+self.zusatzfreibetrag
        self.freibetrag=a
        if self.gehalt > 13:
            self.steuerbetrag=(self.gehalt-self.freibetrag)*45/100
        else:
            self.freibetrag=self.gehalt
            self.nettogehalt=self.gehalt-self.steuerbetrag
        
        print 'Nummer des Zwerges:'+str(self.name)+'\n'
        print 'Beruf:'+str(self.arbeitergruppe)+'\n'
        #print 'Gehalt:'+str(self.gehalt)
        #print 'Basisfreibetrag:'+str(self.basisfreibetrag)
        #print 'Zusatzfreibetrag:'+str(self.zusatzfreibetrag)
        #print 'Freibetrag:'+str(self.freibetrag)
        #print 'Steuer:'+str(self.steuerbetrag)+'\n'
        #print 'Nettogehalt:'+str(self.nettogehalt)+'\n'
        print '------------------------'+'\n'      
"""


class Hofzwerg(Zwerg):
    def __init__(Zwerg):
        self.freibetrag=10
   
#Hofzwerge 1.Klasse
class Hofzwerg1klasse(Hofzwerg):
    def __init__(self):
        self.arbeitergruppe='Hofzwerg 1.Klasse'
        self.gehalt=35
        self.zusatzfreibetrag=3


#Hofzwerge 2.Klasse
class Hofzwerg2klasse(Hofzwerg):
    def __init__(self):
        self.arbeitergruppe='Hofzwerg 2.Klasse'
        self.gehalt=45
        self.zusatzfreibetrag=4


#Basisklass der Zeitarbeiter(Achtung diese Arbeiter werden nach Arbeitszeit bezahlt)
class Zeitarbeiter(Zwerg):
    def __init__(self):
        self.nummer=''
        self.freibetrag=10
       
#Klasse der Kammerkaligraphen
class Kammerkalligraph(Zeitarbeiter):
    def __init__(self):
        self.arbeitergruppe='Kammerkalligraph'
        self.stundenlohn=2
        self.zusatzfreibetrag=3
        self.gehalt=self.stundenlohn*self.zeiteinheit #Berechnung des Gehaltes


#Klasse der Hofpompfuenbristen
class Hofpompfuenebrist(Zeitarbeiter):
    def __init__(self):
        self.arbeitergruppe='Hofpompfuenebrist'
        self.stundenlohn=8
        self.zusatzfreibetrag=3
        self.gehalt=self.zeiteinheit*self.stundenlohn


import random

z=10
b=1
while z > 0:   #Erzeugung der Objekte
    x=int(random.uniform(1,4))
    if x==1:
        e=Hofzwerg1klasse()
    elif x==2:
        e=Hofzwerg2klasse()
    elif x==3:
        e=Kammerkalligraph()
    elif x==4:
        e=Hofpompfuenebristen()
    
    e.name=b
    a=(e.werta)+(e.wertb)
    print str(a)
"""    e.berechnung
    e.ausgabe()"""
    b=b+1
    z=z-1
Zum Testen der Vererbung über 2 Instanzen habe ich die Werte werta und wertb in die Superior Class Zwerg geschrieben. Das Problem ist jetzt, dass die Attribute der Klassen nur einmal vererbt werden(d.h. die 4 Berufsklassen haben zwar die Attribute der Hofzwerge- und der Zeitarbeiterklassen, aber nicht die Attribute der Zwergen Klasse.)
In der Python Documentation steht:
Execution of a derived class definition proceeds the same as for a base class. When the class object is constructed, the base class is remembered. This is used for resolving attribute references: if a requested attribute is not found in the class, the search proceeds to look in the base class. This rule is applied recursively if the base class itself is derived from some other class.
Ich verstehe es einfach nicht. Nach dieser Aussage müsste es einwandfrei funktionieren, da ja Zeitarbeiter und Hofzwerge von Zwerg erben.

Malibu
BlackJack

Die Attribute werden gesetzt, wenn die `__init__()` ausgeführt wird. Dazu musst Du sie aber auch aufrufen. Also zum Beispiel in `Hofzwerg`:

Code: Alles auswählen

class Hofzwerg(Zwerg):
    def __init__(self):
        Zwerg.__init__(self)
        self.freibetrag = 10
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Die __init__-Methode der Mutterklasse wird in Python nicht automatisch aufgerufen. Dies muss explizit erfolgen, z.B. im __init__ von Hofzwerg:

Code: Alles auswählen

Zwerg.__init__(self)
MfG
HWK

Edit: BlackJack war schneller.
Malibu
User
Beiträge: 4
Registriert: Samstag 9. Juni 2007, 12:16

Danke für die schnelle Antwort, aber wenn ich das mache, kommt diese Fehlermeldung:
line 34, in __init__
Zwerg.__init__(self)
NameError: global name 'self' is not defined

Es sieht so aus, als ob er das "self" als Variable sieht, und nicht als Parameter.
BlackJack

`self` ist üblicherweise der Name für das erste Argument in Methoden. Python übergibt als erstes Argument automatisch das Objekt auf dem die Methode aufgerufen wurde. Wenn es also innerhalb einer Methode den Namen `self` nicht gibt, steht er wohl nicht in der Argumentenliste der Methode. Das solltest Du ändern.
Malibu
User
Beiträge: 4
Registriert: Samstag 9. Juni 2007, 12:16

Danke, jetzt macht er was ich will. Warum muss ich aber das Zwerg.__init__(self) woanders hin schreiben? Wird denn nicht schon durch das "def __init__(self)" die Variable der Funktion/Methode angegeben?(Ich fürchte ich hab deine Ausführung mit dem übergeben nicht so ganz verstanden, BlackJack. Ich hab schon lange nicht mehr mit Klassen gearbeitet.)

Hier nochmal das fertige Script:

Code: Alles auswählen

#Theoretische Superior Class, die die Grundwerte der Zwerge festlegt
from __future__ import division

class Zwerg:
    def __init__(self):
        self.name=''
        self.basisfreibetrag=10
        self.steuerbetrag=0

    def ausgabe(self):
        self.freibetrag=self.basisfreibetrag+self.zusatzfreibetrag
        if self.gehalt > self.freibetrag:
            self.steuerbetrag=(self.gehalt-self.freibetrag)*45/100
            self.nettogehalt=self.gehalt-self.steuerbetrag
        else:
            self.nettogehalt=self.gehalt
        
        print 'Nummer des Zwerges:'+str(self.name)
        print 'Beruf:'+str(self.arbeitergruppe)+'\n'
        print 'Gehalt:'+str(self.gehalt)
        if self.arbeitergruppe=='Kammerkalligraph' or self.arbeitergruppe=='Hofpompfuenebrist':
            print 'Zeitraum: '+str(self.zeiteinheit)
        print 'Basisfreibetrag:'+str(self.basisfreibetrag)
        print 'Zusatzfreibetrag:'+str(self.zusatzfreibetrag)
        print 'Freibetrag:'+str(self.freibetrag)
        print 'Steuer:'+str(self.steuerbetrag)+'\n'
        print 'Nettogehalt:'+str(self.nettogehalt)
        print '------------------------'+'\n'

#Basisklasse der Hofzwerge, die aber weggelassen werden kann
'''class Hofzwerg(Zwerg):
    def __init__(self):
        Zwerg.__init__(self)'''

        
#Hofzwerge 1.Klasse
class Hofzwerg1klasse(Zwerg):
    def __init__(self):
        self.arbeitergruppe='Hofzwerg 1.Klasse'
        Zwerg.__init__(self)
        self.gehalt=35
        self.zusatzfreibetrag=3


#Hofzwerge 2.Klasse
class Hofzwerg2klasse(Zwerg):
    def __init__(self):
        self.arbeitergruppe='Hofzwerg 2.Klasse'
        Zwerg.__init__(self)
        self.gehalt=45
        self.zusatzfreibetrag=4


#Basisklass der Zeitarbeiter(werden nach Arbeitszeit bezahlt)
class Zeitarbeiter(Zwerg):
    def __init__(self):
        self.zusatzfreibetrag=3
        Zwerg.__init__(self)
        self.zeiteinheit=int(raw_input('Zeitraum: '))

        
#Klasse der Kammerkaligraphen
class Kammerkalligraph(Zeitarbeiter):
    def __init__(self):
        self.arbeitergruppe='Kammerkalligraph'
        Zeitarbeiter.__init__(self)
        self.stundenlohn=2
        self.gehalt=self.stundenlohn*self.zeiteinheit


#Klasse der Hofpompfuenbristen
class Hofpompfuenebrist(Zeitarbeiter):
    def __init__(self):
        self.arbeitergruppe='Hofpompfuenebrist'
        Zeitarbeiter.__init__(self)
        self.stundenlohn=8
        self.gehalt=self.zeiteinheit*self.stundenlohn



import random

z=10
b=1
while z > 0:   #Erzeugung der Objekte
    x=int(random.uniform(1,5))
    if x==1:
        e=Hofzwerg1klasse()
    elif x==2:
        e=Hofzwerg2klasse()
    elif x==3:
        e=Kammerkalligraph()
    elif x==4:
        e=Hofpompfuenebrist()
    
    e.name=b
    e.ausgabe()
    b=b+1
    z=z-1
Danke für die Hilfe!
Malibu
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Malibu hat geschrieben:Warum muss ich aber das Zwerg.__init__(self) woanders hin schreiben? Wird denn nicht schon durch das "def __init__(self)" die Variable der Funktion/Methode angegeben?
Weil das zwei unterschiedliche Dinge sind. Wenn du ``__init__`` in einer Unterklasse überschreibst (was du mit ``def __init__`` ja machst), dann musst du natürlich auch die ursprüngliche Funktion aufrufen, wenn du willst, dass sie ausgeführt wird.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Malibu hat geschrieben:Danke, jetzt macht er was ich will. Warum muss ich aber das Zwerg.__init__(self) woanders hin schreiben? Wird denn nicht schon durch das "def __init__(self)" die Variable der Funktion/Methode angegeben?
Wenn man eine Methode auf einem Objekt aufruft, dann wird dieses Objekt automatisch als erstes Argument übergeben. Wenn man eine Methode auf einer Klasse aufruft, dann muss man das Objekt natürlich selber übergeben.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Malibu hat geschrieben:Zum Testen der Vererbung über 2 Instanzen habe ich...
Gerade da es sich um eine mündliche Prüfung handelt, wollte ich noch mal darauf hinweisen, dass man über Klassen vererbt und nicht über Instanzen. Klassen beschreiben den Typ und Instanzen sind konkrete Ausprägungen von Klassen. Wobei gerade in Python auch Typen und Klassen selbst wieder Objekte(Instanzen) sind.

Code: Alles auswählen

#Typ/Klasse
class Spam(object):
    pas

#Instanz/Objekt
s = Spam()
Vielleicht solltest du dir den Unterschied noch mal genauer ansehen, aber zumindest ich könnte mir bei einer Prüfung mit OOP-Anteilen nicht die Frage nach dem Unterschied von Klassen und Instanzen verkneifen, da wahrscheinlich die Hälfte auf diese Frage keine richtige Antwort hat.
Malibu
User
Beiträge: 4
Registriert: Samstag 9. Juni 2007, 12:16

Danke für die schnellen Antworten!

@EyDu
Ich wollte mit Instanzen nicht was konkretes sagen sondern meinte damit sowas wie: über mehrere Schritte vererben.
Ich denke ich weiß die Antwort auf die Frage vom Unterschied von Klasse und Objekt(=Instanz?). Trotzdem danke für den Hinweis.

Malibu
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Malibu hat geschrieben:Ich denke ich weiß die Antwort auf die Frage vom Unterschied von Klasse und Objekt(=Instanz?).
"Klasse und Instanz". Denn wie EyDu schon schrieb sind beides Objekte. Nur eben verschiedene.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten