Seite 1 von 1

self in klassen

Verfasst: Samstag 8. Juni 2019, 07:45
von egon11
Die Frage kam glaube ich schon 100x, aber ich bin mir noch nicht zu 100% sicher, was in den Klassen "self" macht.

Hier meine Auffassung:
Wenn man eine Klasse erstellt, und mit den Konstructor die Klasse "__init__(self)" erstellt, wird jede Variable mit "self" voran gestellt, damit sie in jeder Methode verwendbar ist. z.B.

Code: Alles auswählen

sel.x = 4
bedeutet, ich kann mit jeder Methode die Variable "self.x" benutzen.
Wenn ich in "__init__" nur

Code: Alles auswählen

x = 4
code, dann steht mir die Variable nicht in den anderen Methoden zur Verfügung.

Mir nutzt auch nichts, wenn ich in einer "normalen" Methode (z.b.

Code: Alles auswählen

 def meine(self):
eine "self" Variable erzeuge, denn sie ist in einer anderen Methode dann nicht verfügbar.
Also macht es nur in der "__init__" sinn, die Variablen mit "self" zu setzen?
Bei "normalen" Methoden kann ich dann die darin erstellte Variablen ohne "self" seztzen, weil sie ja dann sowieso nur für die Methode greift.

Ist meine Auffassung richtig?

Re: self in klassen

Verfasst: Samstag 8. Juni 2019, 07:55
von ThomasL
Hi egon, eventuell hilfreich könnte diese sehr detaillierte Erklärung hier sein
https://py-tutorial-de.readthedocs.io/d ... asses.html

Re: self in klassen

Verfasst: Samstag 8. Juni 2019, 08:20
von sls
@egon11: __init__ ist kein Konstruktor wie man ihn aus anderen Programmiersprachen wie z.B. Java kennt, sondern ein "Initialisierer". Bei der Initiierung eines neuen Objektes z.B. neues_objekt = Klasse() wird die spezielle __init__-Methode aufgerufen (intern passiert noch mehr, z.B. wird zunächst der __new__-Konstruktor, der dann auch wirklich ein Konstruktor ist, aufgerufen).

Die __init__-Methode ist dafür da, alle Attribute (nicht Variablen) an die Instanz zu koppeln. Das voranstellen von `self` deutet also immer darauf hin, dass das Attribut eine Referenz auf das eigene Objekt bzw. die Klasse ist. Du kannst auch Klassenattribute definieren, die dann zwar außerhalb von Methoden definiert sind, aber noch im Namensraum der Klasse. Diese sind dann ebenfalls über `self` adressierbar, mit dem Unterschied dass diese über mehrere Objekte hinweg zur Verfügung steht, nicht nur auf ein Objekt.

Methoden außerhalb von Klassen nennt man Funktionen in Python.

Es gibt noch classmethods, und staticmethods.

Re: self in klassen

Verfasst: Samstag 8. Juni 2019, 08:28
von __blackjack__
@egon11: Das erste Argument bei Methoden ist das Objekt auf dem die Methode aufgerufen wird. Das hat per Konvention den Namen `self`. Die Initialisierungsmethode `__init__()` (Konstruktor wäre `__new__()`!) wird aufgerufen nach dem das Objekt erstellt wurde und da kann man dann die Attribute auf diesem Objekt setzen. Die kann man danach auch wieder von dem Objekt abfragen. Ausserhalb der Methoden des Objekts, aber eben auch in jeder Methode des Objekts die ja das Objekt *selbst* — darum *self* — als erstes Argument übergeben bekommt.

Man kann auch in anderen Methoden neue Attribute auf dem Objekt setzen so wie man auch ausserhalb von Methoden des Objekts neue Attribute setzen kann, die dann auch überall wieder abgefragt werden können. Das macht man aber in aller Regel nicht, weil das sehr unübersichtlich wird wann welches Objekt welche Attribute hat oder eben auch noch nicht hat, wenn sich da nicht selbst einschränkt. Faustregel: Nachdem die `__init__()` abgelaufen ist, sollte ein Objekt alle Attribute haben und in einem benutzbaren Zustand sein. Das kann manchmal auch bedeuten, dass Attribute zwar existieren, aber beispielsweise an den Wert `None` gebunden sind, weil sie erst im weiteren Verlauf einen anderen Wert bekommen sollen.

Re: self in klassen

Verfasst: Samstag 8. Juni 2019, 09:13
von egon11
Vielen dank, also kann ich in einer anderen Methode

Code: Alles auswählen

def mein(self):
	self.x = 5
kein neues objekt erstellen, welches ich weiter in anderen Methoden nutzen kann?

Re: self in klassen

Verfasst: Samstag 8. Juni 2019, 09:17
von sls
egon11 hat geschrieben: Samstag 8. Juni 2019, 09:13 Vielen dank, also kann ich in einer anderen Methode

Code: Alles auswählen

def mein(self):
	self.x = 5
kein neues objekt erstellen, welches ich weiter in anderen Methoden nutzen kann?

Probiere es aus.

Wenn die anderen Methoden an das selbe Objekt wie `mein` gebunden sind, können sie auf das Attribut x zugreifen. Sie können jedoch nicht auf `x` zugreifen, wenn `x` nicht an `self` gebunden ist und somit nur im lokalen Namensraum der Methode `mein` zur Verfügung steht.

Re: self in klassen

Verfasst: Samstag 8. Juni 2019, 09:30
von __blackjack__
@egon11: Doch das kann man machen sollte man aber nicht. Das hättest Du aber auch einfach ausprobieren können.

Re: self in klassen

Verfasst: Samstag 8. Juni 2019, 10:09
von egon11
__blackjack__ hat geschrieben: Samstag 8. Juni 2019, 09:30 @egon11:Das hättest Du aber auch einfach ausprobieren können.
Das habe ich, hat aber nicht funktioniert.

Re: self in klassen

Verfasst: Samstag 8. Juni 2019, 10:14
von sls
@egon11: was genau hast du probiert? Zeig' doch mal deinen Code.

Re: self in klassen

Verfasst: Samstag 8. Juni 2019, 10:18
von egon11
sls hat geschrieben: Samstag 8. Juni 2019, 10:14 @egon11: was genau hast du probiert? Zeig' doch mal deinen Code.

Code: Alles auswählen

class meinclass:
        def def1(self):
                self.x = 5

        def mein(self):
                c = self.x + 10
                print(c)
meinclass().mein()

Re: self in klassen

Verfasst: Samstag 8. Juni 2019, 10:24
von Sirius3
Und wo wird `def1` aufgerufen? Wie schon mehrfach hier geschrieben, werden in `__init__` die Attribute gesetzt, die die Instanz braucht.

Klassen werden nach Konvention mit Großem Anfangsbuchstaben geschrieben. Die Namen wären auch noch überarbeitenswert. Eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht 8.

Code: Alles auswählen

class Testklasse:
    def __init__(self):
        self.x = 5

    def rechnen(self):
        c = self.x + 10
        print(c)

instanz = Testklasse()
instanz.rechnen()

Re: self in klassen

Verfasst: Samstag 8. Juni 2019, 11:26
von __blackjack__
@egon11: Natürlich ist ein Attribut nicht bekannt wenn es vorher nicht gesetzt wird. Der Code der das Attribut setzt, muss vorher ausgeführt werden. Code in `__init__()` wird ausgeführt wenn das Objekt erszeugt wird. Code in normalen Methoden wird dann ausgeführt, wenn diese Methoden aufgerufen werden. Im Umkehrschluss: Wenn eine Methode nicht aufgerufen wird, dann wird auch der Code darin nicht ausgeführt.

Code: Alles auswählen

#!/usr/bin/env python3

class Class:
    
    def define_x(self):
        self.x = 5

    def do_something(self):
        print(self.x + 10)


def main():
    instance = Class()
    instance.define_x()
    instance.do_something()


if __name__ == '__main__':
    main()
Und wie schon gesagt: das geht technisch, man macht das aber nicht, weil das ganz schnell sehr unübersichtlich wird wenn man immer darüber nachdenken muss wann welches Attribut existiert oder eben nicht existiert. Wenn man ein Objekt erstellt hat, also die `__init__()` ausgeführt wurde, und man sich die Attribute des Objekts auflisten lässt, dann sollten die vollständig sein. Falls nach einem normalen Methodenaufruf ein Objekt plötzlich mehr Attribute als vor dem Aufruf hat, dann ist das ein „code smell“.

Re: self in klassen

Verfasst: Samstag 8. Juni 2019, 16:21
von egon11
OK soweit habe ich es jetzt verstanden, nun kommt leider die nächste Frage auf, und zwar warum funktioniert das in deinem Beispiel, und wenn ich es spaßeshalber abändere, so das es nicht in eine Variable gespeichert wird, nicht?

Code: Alles auswählen

#!/usr/bin/env python3

class Class:
    
    def define_x(self):
        self.x = 5

    def do_something(self):
        print(self.x + 10)


def main():
    Class()
    Class().define_x()
    Class().do_something()

if __name__ == '__main__':
    main()

Re: self in klassen

Verfasst: Samstag 8. Juni 2019, 16:52
von __deets__
Du musst mal genau schauen, was __blackjack__ da schrieb, und was du getan hast. Bei ihm sind da ein paar Gleichheitszeichen mehr, und ein paar Class()-Aufrufe weniger. Und das ist auch das ganze Geheimnis.

Den Konstruktor aufzurufen ERZEUGT ein Objekt. Neu. Jedes mal. Wenn du dir das nicht merkst, dann kannst du es auch nicht veraendern.

Re: self in klassen

Verfasst: Samstag 8. Juni 2019, 16:55
von Sirius3
Was steht in ›main‹?
Erzeuge eine neue Instanz der Klasse ›Class‹ und schmeiß sie weg.
Erzeuge eine neue Instanz der Klasse ›Class‹, definiere das Attribut ›x‹ drin und schmeiß sie weg.
Erzeuge eine neue Instanz der Klasse ›Class‹ und fall auf die Nase, weil diese Instanz noch kein ›x‹ kennt.

Re: self in klassen

Verfasst: Samstag 8. Juni 2019, 17:33
von egon11
OK, jetzt habe ich es verstanden, vielen dank für die Hilfe und jetzt weiß ich es für die Zukunft.
Wenn man das sieht ist es ja logisch :D :D :D