Python gibt uns die Möglichkeit, "private" Methoden und Variablen innerhalb einer Klasse zu erstellen, indem wir dem Namen einen doppelten Unterstrich voranstellen, wie hier: __myPrivateMethod()
. Wie kann man dann dieses Phänomen erklären?
>>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
>>> obj.myPublicMethod()
public method
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
>>> obj._MyClass__myPrivateMethod()
this is private!!
Was ist denn los?!
Für diejenigen, die das nicht ganz verstanden haben, werde ich das ein wenig erklären.
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
Ich erstelle eine Klasse mit einer öffentlichen Methode und einer privaten Methode und instanziiere sie.
Als nächstes rufe ich die öffentliche Methode auf.
>>> obj.myPublicMethod()
public method
Als nächstes versuche ich, die private Methode aufzurufen.
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
Hier sieht alles gut aus; wir sind nicht in der Lage, es zu nennen. Es ist in der Tat "privat". Nun, eigentlich ist es das nicht. Laufend dir() auf das Objekt zeigt eine neue magische Methode, die Python auf magische Weise für alle Ihre "privaten" Methoden erstellt.
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
Der Name dieser neuen Methode ist immer ein Unterstrich, gefolgt vom Klassennamen, gefolgt vom Methodennamen.
>>> obj._MyClass__myPrivateMethod()
this is private!!
So viel zur Verkapselung, was?
Auf jeden Fall hatte ich immer gehört, dass Python keine Kapselung unterstützt, also warum es überhaupt versuchen? Was ist der Grund?
42 Stimmen
Das Gleiche gilt für Java oder C#, wenn Sie Reflection verwenden (was Sie dort ja auch tun).
7 Stimmen
Sie wurde zum Zweck des Unit-Tests erstellt, so dass Sie diesen "Hack" verwenden können, um die privaten Methoden Ihrer Klasse von außen zu testen.
37 Stimmen
Ist das Testen privater Methoden nicht ein Anti-Muster? Private Methoden werden mit Sicherheit in einer öffentlichen Methode verwendet, sonst bleiben sie für immer ungenutzt. Und der richtige Weg, private Methoden zu testen (basierend auf dem, was ich bisher von ThoughtWorks gelernt habe), ist, dass man nur Tests für öffentliche Methoden schreibt, die alle Fälle abdecken. Wenn das gut funktioniert, braucht man private Methoden gar nicht von außen zu testen.
17 Stimmen
@VishnuNarang: Ja, so wird es oft gelehrt. Aber wie immer, ein fast "religiöser" Ansatz von " immer dies tun, niemals das tun" ist das einzige, was "nie" gut ist. Wenn Unit-Tests "nur" für Regressionstests oder zum Testen der öffentlichen API verwendet werden, brauchen Sie private Methoden nicht zu testen. Aber wenn Sie Unit-Test-getriebene Entwicklung betreiben, gibt es gute Gründe, private Methoden während der Entwicklung zu testen (z.B. wenn es schwierig ist, bestimmte ungewöhnliche / extreme Parameter über die öffentliche Schnittstelle zu mocken). Einige Sprachen / Unit-Test-Umgebungen lassen dies nicht zu, was IMHO nicht gut ist.
10 Stimmen
@MarcoFreudenberger Ich verstehe Ihren Standpunkt. Ich habe Erfahrung mit Unit Test Driven Development. Wenn es schwierig wird, Parameter zu mocken, wird das Problem meist durch Änderung und Verbesserung des Designs gelöst. Mir ist noch kein Szenario begegnet, bei dem das Design perfekt ist und Unit-Tests dennoch extrem schwierig sind, um das Testen privater Methoden zu vermeiden. Ich werde nach solchen Fällen Ausschau halten. Ich danke Ihnen. Ich wäre Ihnen dankbar, wenn Sie mir ein Szenario aus dem Stegreif schildern könnten, damit ich es besser verstehe.
1 Stimmen
Ich habe kein gutes Szenario zur Hand, das nicht direkt oder indirekt mit externer Hardware zu tun hat (z. B. arbeite ich viel an Bildverarbeitungssystemen, für bestimmte Werte, die an private Methoden übergeben werden, müssten bestimmte Bilder erstellt werden - was schwierig sein kann -, weil die öffentliche Schnittstelle Bilder von einer Kamera oder von einer Reihe von Testbildern im Falle von Einheitstests nehmen würde).
2 Stimmen
Eine wirklich nette Idee, diese "wir sind alle mündige Erwachsene"-Sache. Tatsache ist, dass in einer ausreichend großen Gruppe von Programmierern, wie in jeder anderen Gruppe auch, das Wissen nicht gleichmäßig verteilt ist. Wenn jeder alles wissen würde, gäbe es Stackoverflow nicht. Hier ein weiteres Zitat: "Ich kam wegen der Philosophie und ging wegen der Realität".
2 Stimmen
@masi Und wenn du mehr als ein einfacher Code-Affe bist, musst du beim Programmieren mehrere Dinge im Kopf jonglieren. Saubere Programmierer machen Methoden klein, um nicht zu viele Dinge im Kopf behalten zu müssen. Wenn ich die Typsicherheit in meinem Kopf emulieren muss, ist das eine weitere Sache, die mich davon abhält, mich auf Architektur und Algorithmen zu konzentrieren.
1 Stimmen
Durch die Offenlegung privater Methoden scheint Python die "Leber, die aus dem Brustkorb hängt" zu bevorzugen, auch wenn sie mit dem Spruch "We are all adults, In Python We Trust" versehen ist.
0 Stimmen
Es ist möglich(isch). Siehe meine Antwort unten: stackoverflow.com/a/64985332/2419960
0 Stimmen
Dieser Mechanismus zur Wahrung der Privatsphäre wird als "name mangling" bezeichnet, bei dem Variablen einfach in etwas Esoterischeres umbenannt werden.