private Attribute

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
PyTimmi

Hallo zusammen,

ich habe gelesen, dass es unter Python-Entwicklern eine Konvention gibt, nach der man von außen nicht direkt auf ein Attribut zugreift, dass mit einem einfachen Unterstrich als Präfix benannt wurde.
Man kann es aber wohl theor. trotzdem machen.

Weiterhin habe ich gelesen, dass man tatsächlich nicht von außen auf ein Attribut zugreifen kann, dass mit dem Präfix doppelter Unterstrich benannt wurde.
Aber ich hab es getestet, man kann es doch.

Worin liegt dann der Unterschied zwischen dem doppelten und dem einfachen Unterstrich?
Und schützt man Attribute dann mit der Built-in Funktion "property"?

Danke und Gruß
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Der doppelte erzeugt eben komplizierteren Namen, der dafür sorgt, dass es nicht zu einer Namenskollision kommen kann. Das kann bei Vererbung und sehr generischen Attributen theoretisch vorkommen. Praktisch habe ich seit Jahren keine doppelten unterstriche mehr verwandt.

Und zur zweiten frage: klares nein. Wenn es nur um normalen Attribut-Zugriff geht, ist es eben ein ohne unterstrich geschriebenes, öffentliches Attribut.
PyTimmi

Ok, danke schon mal für die Antwort.
Was ich aber noch nicht verstehe ist, warum überall zu lesen ist, dass Attribute beginnend mit zwei Unterstrichen private sind und von außen nicht geändert werden können.
Das hab ich ausprobiert und es klappt sehr wohl :D

Code: Alles auswählen

class Auto:
    def __init__(self, farbe, leistung):
        self.__farbe = farbe
        self.__leistung = leistung

traumauto = Auto("rot",300)
traumauto.__farbe = "blau"
Wenn ich mir dann die Farbe des Traumautos per print ausgeben lasse, dann kommt blau.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist aber nicht richtig. Schreib mal eine Methode auf der Klasse, die das Attribut benutzt, zb einfach printed. Und rief die mal auf, nach deiner Zuweisung. Die ist immer noch rot. Garantiert.
PyTimmi

Code: Alles auswählen

class Auto:
    def __init__(self, farbe, leistung):
        self.__farbe = farbe
        self.__leistung = leistung
    
    def farbe_ausgeben(self):
        print(self.__farbe)
​
traumauto = Auto("rot",300)
traumauto.__farbe = "blau"
traumauto.farbe_ausgeben()
Ergebnis: rot

Tatsache. Aber was passiert denn dann in dieser Zeile:

Code: Alles auswählen

traumauto.__farbe = "blau"
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du bindest ein Attribut mit dem Namen an [die Klasse] - Korrektur, das Objekt natürlich 🤦‍♂️. Gib dir mal traumauto.__dict__ aus, dann siehst, was da hinter den Kulissen passiert.
PyTimmi

{'_Auto__farbe': 'rot', '_Auto__leistung': 300, '__farbe': 'blau'}

Das neue Attribut gehört also quasi gar nicht richtig dazu?
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Um noch mal zu dem Schutz zu kommen: Man macht das in Python einfach nicht. Man schreibt *einen* führenden Unterstrich und verlässt sich darauf das Leute das respektieren. Wer das nicht respektiert und damit auf Nase fällt, ist halt selbst Schuld.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Doch, das neue Attribut gehört dazu. Aber kann von in der Klasse nicht einfach benutzt werden. Der Mechanismus versieht alle Attribute mit __ mit einem Klassen-Namen-Präfix. Das wird rein lexikalisch erledigt, der parser weiß ja, wo im Quellcode er ist. Und generiert eben Code, der immer diesen Präfix nutzt. Und damit ist das einfach zu nutzen, aber recht sicher vor kollisionen. Man KANN aber rankommen. Denn du kannst ja den zu sehenden vollen Namen benutzen. Dann kannst du das also auch ändern. Es ist also keine sicherer kapselung.

Und bevor du jetzt zu dem Schluss kommst “aber dann kann ich das ja immer benutzen!” - nein. Es gibt subtile Fehler, die man sich damit einfängt, weil man eben so wie du schon gesehen hast, gar nicht bemerkt, dass man ein neues Attribut anlegt, statt ein bestehendes zu updated. Und im Kontext von Vererbung landet man dann damit auf der Nase. Und wundert sich.
Antworten