Seite 1 von 1

Probleme mit den Klassen

Verfasst: Mittwoch 26. März 2014, 13:42
von Papp Nase
Hallo,

ich habe hier ein kleines Programm zum Üben mit den Klassen geschrieben.

Code: Alles auswählen

# ******************************************************
class MeineKlasse(object):
    def __init__(self):
        self.Wert1 = "Hexen fliegen auf Besen"
        self.Wert2 = 200
        self.Error = 0
        
    def setWerte (self, wert1, wert2):
        self.Wert1 = wert1
        self.Wert2 = wert2
        
    def getError(self):
        return self.Error
# ******************************************************

Testing = MeineKlasse()
print Testing.getError
Testing.setWerte ("1",2)
print Testing.getError
Die Funktion print Testing.getError() liefert leider nicht den Zahlenwert 0, der mit der Funktion __init__ gesetzt wurde, sondern einen langen Ausdruck:
bound methon MeineKlasse.getError of <__main__. MeineKlasse object at 0x0...
Ich habe mich dabei an diesem Link orientiert:

http://www.python-kurs.eu/klassen.php

Leider kann ich meinen Fehler nicht finden, warum ich keinen Zahlenwert angezeigt bekomme, sondern nur diese Speicheradresse.

Re: Probleme mit den Klassen

Verfasst: Mittwoch 26. März 2014, 13:52
von anogayales
Du hast lediglich vergessen die Funktion auch aufzurufen:

Code: Alles auswählen

Testing.getError()
Wenn du lesbaren Python Code schreiben willst nehm die bitte den Style Guide von Python zu Herzen :) http://legacy.python.org/dev/peps/pep-0008/
Grüße,
anogayales

Re: Probleme mit den Klassen

Verfasst: Mittwoch 26. März 2014, 13:53
von Papp Nase
Vielen Dank für Deine schnelle Antwort. Jetzt klapp es :-)

Re: Probleme mit den Klassen

Verfasst: Mittwoch 26. März 2014, 14:06
von BlackJack
@Papp Nase: Als Ergänzung: Das explizite Aufrufen ist nötig weil Methoden ja auch Objekte sind, die man zum Beispiel an Namen binden oder als Argumente bei anderen Aufrufen übergeben kann.

Re: Probleme mit den Klassen

Verfasst: Mittwoch 26. März 2014, 14:36
von Papp Nase
Ich habe mein Programm ein bißchen etwas erweitert:

Code: Alles auswählen

# ******************************************************
class MeineKlasse(object):
    def __init__(self):
        self.Wert1 = "Hexen fliegen auf Besen"
        self.Wert2 = 200
        self.Error = 0
        
    def setWerte (self, wert1, wert2):
        self.Wert1 = wert1
        self.Wert2 = wert2
        
    def getError(self):
        return self.Error
    def getWert1(self):
        return self.Wert1
# ******************************************************

def Hexenfunktion (Anzahl, Textstring):
    rueckwert = MeineKlasse ()
    rueckwert.setWerte (Textstring, Anzahl)
    return (rueckwert)



Testing = MeineKlasse()
print Testing.getError()
print Testing.getWert1()
  
Hexentext = Hexenfunktion (23, "Hexen sitzen auf dem Stuhl")
print Hexentext.getWert1()

Ich habe jetzt eine "Hexenfunktion" eingebaut. In dieser mit def eingeleiteten Funktion wird auch die Klasse "MeineKlasse" verwendet und ein Element "rueckwert" damit erzeugt.

In meinem Programm rufe ich mit "Hexentext = Hexenfunktion (...) diese Funktion auf.

Meine Frage - wenn jetzt die Funktion "Hexenfunktion" abgearbeitet wurde, wird dann das erzeugte Element "rueckwert" automatisch wieder gelöscht oder muss ich manuell den Speicher wieder freigeben mit einem Befehl bzw. einen Destruktor einbauen?

Re: Probleme mit den Klassen

Verfasst: Mittwoch 26. März 2014, 14:51
von BlackJack
@Papp Nase: Du solltest Dich echt mal an die Konventionen halten. Das ist für mich zumindest unnötig schwer lesbar.

Triviale Getter/Setter schreibt man in Python eigentlich auch nicht. Man kann doch direkt auf die Attribute zugreifen. Mindestens bei den beiden `get*()`-Methoden sehe ich keinen Grund die zu schreiben.

Natürlich wird nach abarbeiten der Funktion der Speicher vom Rückgabewert *nicht* freigegeben. Das Objekt wird doch an den aufrufenden Code zurückgegeben und was sollte der dann mit einem Objekt anfangen das bereits freigegeben wurde?

In Python musst Du keine Destruktoren schreiben, die Laufzeitumgebung kümmert sich um den Speicher wenn er nicht mehr vom Programm erreichbar ist. Solange Du nicht *ganz genau* weisst was Du tust, solltest Du niemals eine `__del__()`-Methode schreiben! Und Bücher/Tutorials die Dir `__del__()` als Destruktor erklären und nicht sofort ganz dringend davon abraten diese Methode zu implementieren, solltest Du am besten sofort verbrennen. Wer weiss was die noch für gefährliche Sachen beinhalten. Und zur Frage nach einem Befehl: ``del`` gibt keinen Speicher frei! Damit werden *Namen* gelöscht, nicht Objekte, oder Referenzen auf Objekte in Containerobjekten wie zum Beispiel Listen. Dabei kann Speicher freigegeben werden, muss er aber nicht. Hängt davon ab ob das Objekt danach noch erreichbar ist.

Re: Probleme mit den Klassen

Verfasst: Mittwoch 26. März 2014, 15:02
von Papp Nase
Vielen Dank für Deine Antwort.
@Papp Nae: Du solltest Dich echt mal an die Konventionen halten. Das ist für mich zumindest unnötig schwer lesbar.
Das Beispielprogramm auf dieser Seite:

http://www.python-kurs.eu/klassen.php

sieht von der Strukturierung ähnlich aus wie bei mir.

Ich schreibe z.B.

class ... ():

dann rücke ich die Zeilen entsprechend ein.

Was gibt es an meiner Art der Programmierung dran auszusetzen, ich kann es nicht nachvollziehen? Andere Beispiele auf anderen Homepages sehen ähnlich aus.

Code: Alles auswählen

Natürlich wird nach abarbeiten der Funktion der Speicher vom Rückgabewert *nicht* freigegeben. Das Objekt wird doch an den aufrufenden Code zurückgegeben und was sollte der dann mit einem Objekt anfangen das bereits freigegeben wurde?
Heisst das in diesem Fall, dass es wie ein Pointer ist und ich einfach nur die Speicheradresse übergebe und nicht der Inhalt hin- und herkopiert wird?

Re: Probleme mit den Klassen

Verfasst: Mittwoch 26. März 2014, 15:21
von BlackJack
@Papp Nase: Das einzige was mit Grossbuchstaben anfangen sollte sind Konstanten, die werden Komplett in Grossbuchstaben geschrieben, und Typen, also Klassennamen. Alles andere ist klein_mit_unterstrichen. Das und noch einiges andere steht im Style Guide for Python Code. Wenn ich so etwas wie ``print Testing.getError()`` sehe, dann ist in meinem Hirn fest verdrahtet: Ah, da ruft jemand die statische oder Klassenmethode `getError()` auf der Klasse `Testing` auf.

Python kopiert niemals von sich aus Werte. Das muss man explizit selber tun, wenn man eine Kopie von einem Objekt haben möchte. In der Implementierung wird hinter den Kulissen ein Zeiger zurückgegeben. Wenn man sich mit diesen Implementierungsdetails nicht beschäftigen möchte, viele Anfänger kennen diese Ebene ja gar nicht, kann man einfach sagen es wird das selbe Objekt zurück gegeben welches in der Funktion erzeugt wird.

Bei der verlinkten Seite gleich noch mal eine Anmerkung: Was da über ``public``/``protected``/``private`` steht, stimmt so nicht. In Python gibt es öffentliche Attribute und solche die mit *einem* führenden Unterstrich als Implementierungsdetails gekennzeichnet werden. Attribute mit *zwei* führenden Unterstrichen sind gegen Namenskollisionen bei sehr tiefen Vererbungshierarchien und Mehrfachvererbung gedacht. Beides kommt in Python sehr selten vor und damit sind auch die zwei führenden Unterstriche nur sehr selten sinnvoll. Das man von aussen an diese Attribute nicht heran kommen kann, stimmt nicht, denn das geht sehr wohl, weil die „name mangling”-Regeln dokumentiert sind.