Python gibt uns die Möglichkeit, 'private' Methoden und Variablen innerhalb einer Klasse zu erstellen, indem dem Namen doppelte Unterstriche vorangestellt werden : __myPrivateMethod()
. Wie kann man das dann 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 "", line 1, in
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
>>> obj._MyClass__myPrivateMethod()
this is private!!
Was ist das Problem?!
Ich werde dies ein wenig für diejenigen erklären, die das nicht ganz verstanden haben.
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
Dort habe ich eine Klasse mit einer öffentlichen und einer privaten Methode erstellt und instanziiert.
Als nächstes rufe ich seine öffentliche Methode auf.
>>> obj.myPublicMethod()
public method
Als nächstes versuche ich, seine private Methode aufzurufen.
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "", line 1, in
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
Hier sieht alles gut aus; wir können es nicht nennen. Es ist in der Tat "privat". Nun, eigentlich ist es nicht. Wenn Sie dir () für das Objekt ausführen, wird eine neue magische Methode angezeigt, 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!!
Soviel zur Kapselung, was?
Auf jeden Fall hatte ich immer gehört, dass Python die Kapselung nicht unterstützt. Warum also überhaupt versuchen? Was gibt?
Antworten:
Die Namensverschlüsselung wird verwendet, um sicherzustellen, dass Unterklassen die privaten Methoden und Attribute ihrer Oberklassen nicht versehentlich überschreiben. Es soll nicht den absichtlichen Zugriff von außen verhindern.
Zum Beispiel:
Natürlich bricht es zusammen, wenn zwei verschiedene Klassen den gleichen Namen haben.
quelle
Beispiel einer privaten Funktion
quelle
self = MyClass()
self.private_function()
. : D Natürlich funktioniert es nicht in Klassen, aber Sie müssen nur eine benutzerdefinierte Funktion definieren:def foo(self): self.private_function()
function_call.startswith('self.')
.inspect.stack()[1][4][0].strip()
<- Was sind diese magischen Zahlen 1, 4 und 0?self = MyClass(); self.private_function()
und schlägt fehl, wenn esx = self.private_function()
innerhalb einer Methode aufgerufen wird.Als ich zum ersten Mal von Java nach Python kam, hasste ich das. Es hat mich zu Tode erschreckt.
Heute ist es vielleicht das Einzige, was ich an Python am meisten liebe .
Ich liebe es, auf einer Plattform zu sein, auf der sich die Leute gegenseitig vertrauen und nicht das Gefühl haben, undurchdringliche Wände um ihren Code bauen zu müssen. Wenn in stark gekapselten Sprachen eine API einen Fehler aufweist und Sie herausgefunden haben, was schief geht, können Sie ihn möglicherweise immer noch nicht umgehen, da die erforderliche Methode privat ist. In Python lautet die Einstellung: "sicher". Wenn Sie denken, Sie verstehen die Situation, vielleicht haben Sie sie sogar gelesen, dann können wir nur "viel Glück!" Sagen.
Denken Sie daran, dass die Kapselung nicht einmal schwach mit "Sicherheit" zusammenhängt oder die Kinder vom Rasen fernhält. Es ist nur ein weiteres Muster, das verwendet werden sollte, um das Verständnis einer Codebasis zu erleichtern.
quelle
Von http://www.faqs.org/docs/diveintopython/fileinfo_private.html
quelle
Der häufig verwendete Ausdruck lautet "Wir stimmen hier allen Erwachsenen zu". Indem Sie einen einzelnen Unterstrich (nicht verfügbar machen) oder einen doppelten Unterstrich (ausblenden) voranstellen, teilen Sie dem Benutzer Ihrer Klasse mit, dass das Mitglied in irgendeiner Weise "privat" sein soll. Sie vertrauen jedoch darauf, dass sich alle anderen verantwortungsbewusst verhalten und dies respektieren, es sei denn, sie haben einen zwingenden Grund, dies nicht zu tun (z. B. Debugger, Code-Vervollständigung).
Wenn Sie wirklich etwas Privates haben müssen, können Sie es in einer Erweiterung implementieren (z. B. in C für CPython). In den meisten Fällen lernen Sie jedoch einfach die pythonische Vorgehensweise.
quelle
Es ist nicht so, dass Sie die Privatsphäre von Mitgliedern in keiner Sprache umgehen können (Zeigerarithmetik in C ++, Reflections in .NET / Java).
Der Punkt ist, dass Sie eine Fehlermeldung erhalten, wenn Sie versuchen, die private Methode versehentlich aufzurufen. Aber wenn Sie sich in den Fuß schießen wollen, machen Sie es einfach.
Bearbeiten: Sie versuchen nicht, Ihre Sachen durch OO-Kapselung zu sichern, oder?
quelle
Die
class.__stuff
Namenskonvention teilt dem Programmierer mit, dass er nicht__stuff
von außen darauf zugreifen soll . Der Name Mangling macht es unwahrscheinlich, dass jemand es versehentlich tun wird.Sie können das zwar noch umgehen, es ist sogar noch einfacher als in anderen Sprachen (die Sie übrigens auch zulassen), aber kein Python-Programmierer würde dies tun, wenn er sich um die Kapselung kümmert.
quelle
Ein ähnliches Verhalten tritt auf, wenn Modulattributnamen mit einem einzelnen Unterstrich beginnen (z. B. _foo).
Als solche bezeichnete Modulattribute werden bei Verwendung der
from*
Methode nicht in ein importierendes Modul kopiert , z.Dies ist jedoch eine Konvention und keine Sprachbeschränkung. Dies sind keine privaten Attribute. Sie können von jedem Importeur referenziert und manipuliert werden. Einige argumentieren, dass Python aus diesem Grund keine echte Kapselung implementieren kann.
quelle
Dies ist nur eine dieser Optionen für das Sprachdesign. In gewisser Hinsicht sind sie gerechtfertigt. Sie machen es so, dass Sie ziemlich weit aus dem Weg gehen müssen, um zu versuchen, die Methode aufzurufen, und wenn Sie es wirklich so dringend brauchen, müssen Sie einen ziemlich guten Grund haben!
Debugging-Hooks und Tests kommen als mögliche Anwendungen in den Sinn, die natürlich verantwortungsbewusst eingesetzt werden.
quelle
Mit Python 3.4 ist dies das Verhalten:
https://docs.python.org/3/tutorial/classes.html#tut-private
Selbst wenn die Frage alt ist, hoffe ich, dass mein Ausschnitt hilfreich sein könnte.
quelle
Das wichtigste Anliegen bei privaten Methoden und Attributen ist, den Entwicklern anzuweisen, sie nicht außerhalb der Klasse aufzurufen. Dies ist die Kapselung. Man kann die Sicherheit durch Kapselung falsch verstehen. Wenn man absichtlich die von Ihnen erwähnte Syntax (unten) verwendet, möchten Sie keine Kapselung.
Ich bin von C # migriert und anfangs war es auch komisch für mich, aber nach einer Weile kam ich auf die Idee, dass nur die Art und Weise, wie Python-Code-Designer über OOP denken, anders ist.
quelle
So wie ich es verstehe, können sie nicht privat sein. Wie könnte die Privatsphäre durchgesetzt werden?
Die offensichtliche Antwort lautet "Auf private Mitglieder kann nur über zugegriffen werden
self
", aber das würde nicht funktionieren -self
ist in Python nichts Besonderes, es ist nichts weiter als ein häufig verwendeter Name für den ersten Parameter einer Funktion.quelle