Bei Zweifel, lass es "public" - das heißt, füge nichts hinzu, um den Namen deines Attributs zu verbergen. Wenn Sie eine Klasse mit einem internen Wert haben, kümmern Sie sich nicht darum. Anstatt zu schreiben:
class Stack(object):
def __init__(self):
self.__storage = [] # Zu steif
def push(self, value):
self.__storage.append(value)
Schreibe stattdessen standardmäßig folgendes:
class Stack(object):
def __init__(self):
self.storage = [] # Kein Verstümmeln
def push(self, value):
self.storage.append(value)
Dies ist sicherlich ein kontroverser Weg, Dinge zu tun. Python-Neulinge hassen es, und auch einige alte Python-Leute verachten dieses Standardverhalten - aber es ist sowieso der Standard, daher empfehle ich Ihnen, ihm zu folgen, auch wenn Sie sich unwohl fühlen.
Wenn Sie wirklich die Nachricht "Kann nicht berührt werden!" an Ihre Benutzer senden möchten, ist der übliche Weg, die Variable mit einem Unterstrich voranzustellen. Dies ist nur eine Konvention, aber die Leute verstehen es und achten besonders darauf, wenn sie mit solchen Dingen umgehen:
class Stack(object):
def __init__(self):
self._storage = [] # Das ist in Ordnung, aber die Pythonistas verwenden es, um entspannter zu sein
def push(self, value):
self._storage.append(value)
Dies kann auch nützlich sein, um Konflikte zwischen Eigenschaftsnamen und Attributnamen zu vermeiden:
class Person(object):
def __init__(self, name, age):
self.name = name
self._age = age if age >= 0 else 0
@property
def age(self):
return self._age
@age.setter
def age(self, age):
if age >= 0:
self._age = age
else:
self._age = 0
Was ist mit dem doppelten Unterstrich? Nun, wir verwenden den doppelten Unterstrich hauptsächlich um versehentliche Überladung von Methoden und Namenskonflikte mit Attributen von Superklassen zu vermeiden. Es kann ziemlich wertvoll sein, wenn Sie eine Klasse schreiben, die viele Male erweitert werden soll.
Wenn Sie es für andere Zwecke verwenden möchten, können Sie dies tun, aber es ist weder üblich noch empfohlen.
BEARBEITEN: Warum ist das so? Nun, der übliche Python-Stil betont nicht die Privatsphäre - im Gegenteil! Es gibt viele Gründe dafür - die meisten von ihnen kontrovers... Lassen Sie uns einige davon sehen.
Eigenschaften in Python
Heutzutage verwenden die meisten OO-Sprachen den entgegengesetzten Ansatz: Was nicht verwendet werden sollte, sollte nicht sichtbar sein, daher sollten Attribute privat sein. Theoretisch würde dies wohl verwaldbarere, weniger gekoppelte Klassen ergeben, weil niemand die Werte der Objekte leichtfertig ändern würde.
Aber es ist nicht so einfach. Beispielsweise haben Java-Klassen viele Getter, die nur Werte holen und Setter, die nur Werte setzen. Sie benötigen, sagen wir, sieben Zeilen Code, um ein einziges Attribut zu deklarieren - was ein Python-Programmierer als unnötig komplex bezeichnen würde. Außerdem schreiben Sie viel Code, um ein öffentliches Feld zu erhalten, da Sie den Wert praktisch mit den Gettern und Settern ändern können.
Warum also dieser privat-nach-Standard-Politik folgen? Machen Sie Ihre Attribute einfach standardmäßig öffentlich. Natürlich ist dies in Java problematisch, denn wenn Sie beschließen, eine Validierung zu Ihrem Attribut hinzuzufügen, müssten Sie alle:
person.age = age;
in Ihrem Code zu, sagen wir,
person.setAge(age);
setAge()
sein:
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
this.age = 0;
}
}
In Java (und anderen Sprachen) ist also der Standard, trotzdem Getter und Setter zu verwenden, denn sie können zwar nervig zu schreiben sein, können Ihnen aber viel Zeit sparen, wenn Sie sich in der von mir beschriebenen Situation befinden.
Aber in Python müssen Sie es nicht tun, da Python Eigenschaften hat. Wenn Sie diese Klasse haben:
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
...und dann beschließen, Altersvalidierungen vorzunehmen, müssen Sie die Stücke Ihres Codes, in denen person.age = age
steht, nicht ändern. Fügen Sie einfach eine Eigenschaft hinzu (wie unten gezeigt)
class Person(object):
def __init__(self, name, age):
self.name = name
self._age = age if age >= 0 else 0
@property
def age(self):
return self._age
@age.setter
def age(self, age):
if age >= 0:
self._age = age
else:
self._age = 0
Wenn Sie das tun können und trotzdem person.age = age
verwenden, warum würden Sie dann private Felder und Getter und Setter hinzufügen?
(Siehe auch Python ist nicht Java und diesen Artikel über die Nachteile der Verwendung von Gettern und Settern).
Alles ist sowieso sichtbar - und der Versuch, zu verbergen, macht die Arbeit kompliziert
Auch in Sprachen mit privaten Attributen können Sie auf sie über eine Reflection/Introspection-Bibliothek zugreifen. Und die Leute tun das viel, in Frameworks und zur Bewältigung von dringenden Bedürfnissen. Das Problem ist, dass Introspektionsbibliotheken nur einen komplizierten Weg darstellen, um das zu tun, was Sie mit öffentlichen Attributen tun könnten.
Da Python eine sehr dynamische Sprache ist, ist es kontraproduktiv, diese Last Ihren Klassen hinzuzufügen.
Das Problem ist nicht nicht sehen zu können - sondern müssen sehen zu müssen
Für einen Pythonista ist die Kapselung nicht die Unfähigkeit, die internen Details von Klassen zu sehen, sondern die Möglichkeit, sie zu vermeiden. Kapselung ist die Eigenschaft eines Komponenten, die der Benutzer ohne Rücksicht auf interne Details verwenden kann. Wenn Sie eine Komponente verwenden können, ohne sich über ihre Implementierung Gedanken machen zu müssen, dann ist sie (in der Meinung eines Python-Programmierers) kapsuliert.
Jetzt, wenn Sie eine Klasse geschrieben haben, die Sie ohne Nachdenken über Implementierungsdetails verwenden können, ist es kein Problem, wenn Sie aus irgendeinem Grund möchten, in die Klasse hineinzuschauen. Der Punkt ist: Ihre API sollte gut sein, und der Rest sind Details.
Guido hat es gesagt
Nun, das ist nicht umstritten: er hat es tatsächlich gesagt. (Suchen Sie nach "offenes Kimono.")
Dies ist Kultur
Ja, es gibt einige Gründe, aber keinen kritischen Grund. Dies ist hauptsächlich ein kultureller Aspekt des Programmierens in Python. Ehrlich gesagt könnte es auch anders sein - ist es aber nicht. Sie könnten genauso gut fragen, warum einige Sprachen standardmäßig private Attribute verwenden? Aus dem gleichen Hauptgrund wie für die Praxis in Python: weil es die Kultur dieser Sprachen ist, und jede Wahl hat Vor- und Nachteile.
Da es bereits diese Kultur gibt, ist es ratsam, ihr zu folgen. Andernfalls werden Sie von Python-Programmierern genervt sein, die Ihnen sagen, dass Sie das __
aus Ihrem Code entfernen sollen, wenn Sie eine Frage auf Stack Overflow stellen :)