kaineanung hat geschrieben:Auch wenn ich immer noch nicht ganz verstehe warum ich in der Klasse keine echten 'private'-Funktionen benutzen soll sondern die 'protected'. Das erste wird laut python-tutorial mit doppelten Unterstrichen deklariert und das Zweite, also die protected-Funktionen, nur mit einem Unterstrich.
private ist laut Tutorial definitiv privat und nicht überladbar in vererbten Klassen und protected eben nur 'semi-privat'. Man soll sie nicht ändern, man kann sie ändern in einer vererbten Klasse.
Nun gut, das ist ja wohl die Philosophie von OOP und dem Überladen und sicherlich ist es dem geschuldet daß ihr mir sagt die Funktionen sollen protected sein, richtig?
Nein, nicht richtig. Ich weiß nicht, welches Tutorial du verwendest, aber wenn da steht, dass in Python irgendwas protected wäre, ist es ein schlechtes Tutorial, weil das eben nicht stimmt.
Attributnamen mit einem führenden Unterstrich bedeuten: ist ein Implementierungsdetail und gehört nicht zur öffentlichen Schnittstelle. Die öffentliche Schnittstelle ist das, was man benutzen soll, aber nichts hindert einen daran, auch auf Implementierungsdetails zuzugreifen. Man tut das dann aber auf eigenes Risiko, denn manchmal funktioniert etwas nicht mehr, wenn man von außen an Implementierungsdetails rumfummelt. Außerdem können sich die Implementierungsdetails in der nächsten Version ohne Vorwarnung ändern, so dass dann Code, der darauf zugreift evtl. nicht mehr funktioniert.
Attributnamen mit zwei führenden Unterstrichen, die nicht mit zwei Unterstrichen enden, unterliegen dem sog. private name mangling. Das bedeutet, der tatsächliche Name wird umgebastelt, so dass der Klassenname mit hineingewurstelt wird. Dadurch können bei Mehrfachvererbung zwei Basisklassen Attribute mit denselben Namen haben ohne sich in die Quere zu kommen. Aber das Mangling ist genau definiert. Wenn ein Attribut __foo in einer Klasse Bar definiert ist, dann wird daraus der Name _Bar__foo, und den kann ich verwenden, denn in Python ist eben nichts privat:
Code: Alles auswählen
In [1]: class Bar:
...: __foo = 1
...:
In [2]: Bar._Bar__foo
Out[2]: 1
In [3]: Bar._Bar__foo = 2
In [4]: Bar._Bar__foo
Out[4]: 2