Warum sind Pythons ‚private‘ Methoden nicht wirklich privat?
-
09-06-2019 - |
Frage
Python gibt uns die Möglichkeit, durch das Voranstellen doppelte Unterstrichen auf den Namen, wie diese ‚private‘ Methoden und Variablen innerhalb einer Klasse zu erstellen: __myPrivateMethod()
. Wie also kann man das 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 diese ein wenig für diejenigen erklären, die nicht ganz so bekommen haben.
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
Was ich tat, es gibt eine Klasse mit einer öffentlichen Methode erstellen und ein eigenes Verfahren und instanziiert es.
Als nächstes rufe ich seine öffentliche Methode.
>>> obj.myPublicMethod()
public method
Als nächstes versuche ich, und seine private Methode nennen.
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "", line 1, in
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
Alles sieht hier gut; wir sind nicht in der Lage, es zu nennen. Es ist in der Tat, ‚privat‘. Na ja, eigentlich ist es nicht. Ausführen von dir () auf dem Objekt eine neue magische Methode zeigt, dass 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, durch den Klassennamen, gefolgt von dem Methodennamen gefolgt.
>>> obj._MyClass__myPrivateMethod()
this is private!!
So viel zur Verkapselung, wie?
Auf jeden Fall würde ich immer gehört, Python nicht Verkapselung nicht unterstützt, also warum auch versuchen? Was soll das?
Lösung
Der Name wird Scrambling verwendet, um sicherzustellen, dass Unterklassen die privaten Methoden und Attribute ihrer Oberklassen nicht versehentlich überschrieben werden. Es ist nicht zu verhindern, dass bewusster Zugang von außen ausgelegt.
Zum Beispiel:
>>> class Foo(object):
... def __init__(self):
... self.__baz = 42
... def foo(self):
... print self.__baz
...
>>> class Bar(Foo):
... def __init__(self):
... super(Bar, self).__init__()
... self.__baz = 21
... def bar(self):
... print self.__baz
...
>>> x = Bar()
>>> x.foo()
42
>>> x.bar()
21
>>> print x.__dict__
{'_Bar__baz': 21, '_Foo__baz': 42}
Natürlich ist es bricht, wenn zwei verschiedene Klassen den gleichen Namen haben.
Andere Tipps
Beispiel für private Funktion
import re
import inspect
class MyClass :
def __init__(self) :
pass
def private_function ( self ) :
try :
function_call = inspect.stack()[1][4][0].strip()
# See if the function_call has "self." in the begining
matched = re.match( '^self\.', function_call )
if not matched :
print 'This is Private Function, Go Away'
return
except :
print 'This is Private Function, Go Away'
return
# This is the real Function, only accessible inside class #
print 'Hey, Welcome in to function'
def public_function ( self ) :
# i can call private function from inside the class
self.private_function()
### End ###
Als ich zuerst von Java nach Python kam I gehasst diese. Es erschreckt mich zu Tode.
Heute könnte es nur sein, die eine Sache, Ich liebe die meisten über Python.
Ich liebe auf einer Plattform zu sein, wo die Menschen einander vertrauen und nicht das Gefühl, wie sie sich um ihren Code undurchdringlichen Mauern bauen müssen. In stark gekapselt Sprachen, wenn eine API einen Fehler hat, und Sie haben herausgefunden, was schief geht, können Sie immer noch nicht in der Lage sein, um es zu arbeiten, weil die benötigte Methode privat ist. In Python ist die Haltung: „sicher“. Wenn Sie glauben, die Situation zu verstehen, vielleicht haben Sie es sogar lesen, dann alles, was wir sagen können, ist „viel Glück!“.
Denken Sie daran, Verkapselung nicht einmal schwach zu „Sicherheit“ im Zusammenhang, oder die Kinder aus dem Rasen zu halten. Es ist nur ein weiteres Muster, das verwendet werden soll, eine Code-Basis leichter verständlich zu machen.
http://www.faqs.org/docs/diveintopython/fileinfo_private.html
Genau genommen private Methoden sind außerhalb ihrer Klasse zugänglich, nur nicht leicht zugänglich. Nichts in Python ist wirklich privat; im Inneren, die Namen von privaten Methoden und Attribute sind verstümmelten und unmangled on the fly, um sie scheinen unzugänglich durch ihre Vornamen. Sie Zugriff auf die __parse Verfahren des Dosen MP3FileInfo Klasse mit dem Namen _MP3FileInfo__parse. Bestätigen Sie, dass dies interessant, dann versprechen, nie, tun Sie es jemals in echten Code. Private Methoden sind privat für ein Grund, aber wie viele andere Dinge in Python, ihre Privatheit ist letztlich eine Frage der Konvention, nicht Kraft.
Der Begriff häufig verwendet, ist „wir sind alle Erwachsene zustimmenden hier“. Durch das Voranstellen eines einzelnen Strich (nicht aussetzen) oder Doppelstrich (ausblenden), doch sagen Sie den Benutzer Ihrer Klasse, die Sie das Mitglied beabsichtigen, in irgendeiner Weise ‚privat‘ zu sein. Aber Sie vertrauen, alle anderen verhalten verantwortungsvoll und respektieren, dass, es sei denn, sie haben einen zwingenden Grund, nicht zu (zum Beispiel Debugger, Code-Vervollständigung).
Wenn Sie wirklich etwas haben muss, was privat ist, dann können Sie es in einer Erweiterung implementieren (beispielsweise in C für CPython). In den meisten Fällen jedoch lernen Sie einfach die Pythonic Art und Weise, Dinge zu tun.
Es ist nicht absolut nicht wie um Privatheit der Mitglieder in jeder Sprache (Zeiger arithmetics in C ++, Reflections in .NET / Java) erhalten kann.
Der Punkt ist, dass Sie eine Fehlermeldung erhalten, wenn Sie versuchen, die private Methode durch Zufall zu nennen. Aber wenn man sich in den Fuß schießen wollen, gehen Sie voran und es tun.
Edit:? Sie versuchen Sie nicht, Ihre Sachen durch OO-Verkapselung zu sichern, haben Sie
Die class.__stuff
Namenskonvention ermöglicht der Programmierer weiß, dass er nicht __stuff
von außen zugreifen soll. Der Name Mangeln macht es unwahrscheinlich, jemand es durch Zufall tun.
Es stimmt, können Sie immer noch dieses Problem umgehen, ist es noch einfacher als in anderen Sprachen (die übrigens auch lassen Sie dies tun), aber kein Python-Programmierer würde dies tun, wenn er über Verkapselung sorgt.
Ein ähnliches Verhalten liegt vor, wenn Modul Attributnamen mit einem einzigen Unterstrich beginnen (zum Beispiel _foo).
Modul Attribute als solche benannt werden nicht in ein Importmodul kopiert werden, wenn die from*
Methode verwendet, z.
from bar import *
Dies ist jedoch eine Konvention und keine Sprache Einschränkung. Diese sind nicht private Attribute; sie können von jedem Importeur referenziert und manipuliert werden. Einige argumentieren, dass aus diesem Grunde, Python nicht wahr Verkapselung implementieren kann.
Es ist nur eine dieser Sprache Design-Entscheidungen. Auf einer bestimmten Ebene sind sie gerechtfertigt. Sie machen es, so dass Sie ziemlich weit aus dem Weg gehen müssen, um die Methode zu versuchen, und zu rufen, und wenn Sie es wirklich brauchen, die schlecht, müssen Sie einen ziemlich guten Grund haben!
Debuggen Haken und kamen Tests als mögliche Anwendungen in dem Sinne, verantwortungs natürlich verwendet werden.
Mit Python 3.4 ist dies das Verhalten:
>>> class Foo:
def __init__(self):
pass
def __privateMethod(self):
return 3
def invoke(self):
return self.__privateMethod()
>>> help(Foo)
Help on class Foo in module __main__:
class Foo(builtins.object)
| Methods defined here:
|
| __init__(self)
|
| invoke(self)
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
>>> f = Foo()
>>> f.invoke()
3
>>> f.__privateMethod()
Traceback (most recent call last):
File "<pyshell#47>", line 1, in <module>
f.__privateMethod()
AttributeError: 'Foo' object has no attribute '__privateMethod'
https://docs.python.org/3/tutorial /classes.html#tut-private
Beachten Sie, dass die Mangeln Regeln ausgelegt sind meist um Unfälle zu vermeiden; es noch möglich ist, zuzugreifen oder eine Variable zu ändern, die privat angesehen wird. Dies auch nützlich in besonderen Umständen sein kann, wie in dem Debugger.
Auch wenn die Frage alt ist, ich hoffe, dass mein Snippet hilfreich sein könnte.
Die wichtigste Sorge über private Methoden und Attribute ist es, Entwickler zu sagen nicht, dass es außerhalb der Klasse zu nennen und dies ist Kapselung. kann man die Sicherheit von Verkapselung falsch verstehen. wenn man bewusst Syntax wie die verwendet (unten) Sie erwähnt haben, wollen Sie nicht Kapselung.
obj._MyClass__myPrivateMethod()
Ich habe von C # migriert und anfangs war es auch für mich komisch, aber nach einer Weile kam ich auf die Idee, dass nur die Art und Weise, dass Python-Code Designer denken über OOP unterscheidet.
Warum sind Pythons 'private' Methoden nicht wirklich privat?
Wie ich es verstehe, sie nicht privat sein. Wie könnte die Privatsphäre durchgesetzt werden?
Die offensichtliche Antwort ist „private Mitglieder können nur durch self
zugegriffen werden“, aber das würde nicht funktionieren - self
in Python nicht speziell ist, ist es nichts anderes als eine häufig verwendete Bezeichnung für den ersten Parameter einer Funktion.