variable - static private method python




Warum sind Pythons "private" Methoden nicht wirklich privat? (8)

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 ###

Python gibt uns die Möglichkeit, "private" Methoden und Variablen innerhalb einer Klasse zu erstellen, indem wir dem Namen doppelte Unterstriche __myPrivateMethod() : __myPrivateMethod() . Wie 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 das 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()

Was ich dort gemacht habe, ist eine Klasse mit einer öffentlichen Methode und einer privaten Methode zu erstellen und instanziieren.

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. Das Ausführen von dir () auf dem Objekt zeigt eine neue magische Methode, die Python auf magische Weise für all 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 Kapselung, oder?

In jedem Fall hatte ich schon immer gehört, dass Python die Kapselung nicht unterstützt. Warum also überhaupt versuchen? Was gibt?


Als ich zum ersten Mal von Java nach Python kam, hasste ich das. Es hat mich zu Tode erschreckt.

Heute könnte es einfach die eine Sache sein, die ich an Python am meisten liebe .

Ich mag es, auf einer Plattform zu sein, wo Menschen einander vertrauen und nicht das Gefühl haben, dass sie undurchdringliche Mauern um ihren Code herum bauen müssen. Wenn in stark gekapselten Sprachen eine API einen Fehler aufweist und Sie herausgefunden haben, was schief läuft, können Sie möglicherweise immer noch nicht daran herumarbeiten, da die erforderliche Methode privat ist. In Python ist die Einstellung: "sicher". Wenn du denkst, dass du die Situation verstehst, hast du sie vielleicht sogar gelesen, dann können wir nur "viel Glück!" Sagen.

Denken Sie daran, Kapselung ist nicht einmal schwach mit "Sicherheit" verbunden, oder die Kinder vom Rasen zu halten. Es ist nur ein weiteres Muster, das verwendet werden sollte, um eine Codebasis leichter verständlich zu machen.


Das wichtigste Problem bei privaten Methoden und Attributen besteht darin, den Entwicklern mitzuteilen, dass sie nicht außerhalb der Klasse aufgerufen werden sollen, und dies ist die Kapselung. Man kann die Sicherheit der Kapselung missverstehen. Wenn Sie eine Syntax wie diese (siehe unten) bewusst verwenden, möchten Sie keine Kapselung.

obj._MyClass__myPrivateMethod()

Ich bin von C # migriert und zuerst war es auch komisch für mich, aber nach einer Weile kam ich auf die Idee, dass nur die Art, wie Python-Code-Designer über OOP denken, anders ist.


Der Name scrambling wird verwendet, um sicherzustellen, dass Unterklassen die privaten Methoden und Attribute ihrer Oberklassen nicht versehentlich überschreiben. Es ist nicht dazu gedacht, einen vorsätzlichen Zugriff von außen zu verhindern.

Beispielsweise:

>>> 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 bricht es zusammen, wenn zwei verschiedene Klassen den gleichen Namen haben.


Die Namenskonvention der class.__stuff lässt den Programmierer wissen, dass er nicht von außen auf __stuff zugreifen __stuff . Der Name Mangling macht es unwahrscheinlich, dass jemand es aus Versehen tut.

Es stimmt, du kannst immer noch damit umgehen, es ist sogar einfacher als in anderen Sprachen (was BTW dir auch erlaubt), aber kein Python-Programmierer würde das tun, wenn er sich um die Kapselung kümmert.


Ein ähnliches Verhalten tritt auf, wenn Modulattributnamen mit einem einzelnen Unterstrich beginnen (z. B. _foo).

Als solche bezeichnete Modulattribute werden bei Verwendung der Methode from* nicht in ein Importmodul kopiert, z. B .:

from bar import *

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 deshalb keine echte Kapselung implementieren kann.


Es ist nur eine dieser Sprachdesign-Optionen. Auf einer gewissen Ebene sind sie gerechtfertigt. Sie machen es so, dass du ziemlich weit weg gehen musst, um die Methode zu nennen, und wenn du sie wirklich so dringend brauchst, musst du einen recht guten Grund haben!

Debugging-Haken und Tests kommen mir als mögliche Anwendungen in den Sinn, die natürlich verantwortungsvoll genutzt werden.


Von http://www.faqs.org/docs/diveintopython/fileinfo_private.html

Streng genommen sind private Methoden außerhalb ihrer Klasse zugänglich, einfach nicht leicht zugänglich. Nichts in Python ist wirklich privat. intern werden die Namen von privaten Methoden und Attributen im laufenden Betrieb gemangelt und nicht gemanagt, um sie durch ihre Vornamen unzugänglich zu machen. Sie können auf die __parse-Methode der MP3FileInfo-Klasse mit dem Namen _MP3FileInfo__parse zugreifen. Bestätigen Sie, dass dies interessant ist, und versprechen Sie, dass Sie es niemals in echtem Code tun werden. Private Methoden sind aus einem Grund privat, aber wie viele andere Dinge in Python ist ihre Privatsphäre letztlich eine Frage der Konvention, nicht der Gewalt.





information-hiding