Dlaczego metody Pythona nie są tak naprawdę prywatne?

Python daje nam możliwość tworzenia' prywatnych ' metod i zmiennych w obrębie klasy poprzez dołączanie podwójnych znaków podkreślenia do nazwy, jak to: __myPrivateMethod(). Jak zatem można to wyjaśnić

>>> 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!!
O co chodzi?! Wyjaśnię to trochę tym, którzy tego nie rozumieli.
>>> class MyClass:
...     def myPublicMethod(self):
...             print 'public method'
...     def __myPrivateMethod(self):
...             print 'this is private!!'
... 
>>> obj = MyClass()

To, co zrobiłem, to stworzenie klasy z metodą publiczną i metodą prywatną i utworzenie jej instancji.

Następnie, nazywam jego metodę publiczną.

>>> obj.myPublicMethod()
public method

Następny, Próbuję nazwać to prywatną metodą.

>>> obj.__myPrivateMethod()
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
Wszystko wygląda tu dobrze, nie możemy tego nazwać. W rzeczywistości jest to "prywatne". W rzeczywistości nie jest. uruchomienie dir () na obiekcie ujawnia nową magiczną metodę, którą python tworzy magicznie dla wszystkich Twoich "prywatnych" metod.
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']

Nazwa nowej metody jest zawsze podkreśleniem, po którym następuje nazwa klasy, po której następuje nazwa metody.

>>> obj._MyClass__myPrivateMethod()
this is private!!
To by było na tyle, jeśli chodzi o enkapsulację, co?

W każdym razie, zawsze słyszałem, że Python nie obsługuje enkapsulacji, więc po co w ogóle próbować? Co jest?

Author: Stefan van den Akker, 2008-09-16

13 answers

Nazwa scrambling jest używana, aby upewnić się, że podklasy nie przypadkowo nadpisują prywatnych metod i atrybutów ich superklas. Nie jest zaprojektowany, aby zapobiec celowemu dostępowi z zewnątrz.

Na przykład:

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

Oczywiście rozkłada się, jeśli dwie różne klasy mają tę samą nazwę.

 617
Author: Alya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 10:06:07

Przykład funkcji prywatnej

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 ###
 213
Author: arun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-29 12:52:47

Kiedy po raz pierwszy przeszedłem z Javy do Pythona i nienawidziłem tego. Przeraziło mnie to na śmierć.

Dziś może być to jedyna rzecz , którą najbardziej kocham w Pythonie.

Uwielbiam być na platformie, gdzie ludzie sobie ufają i nie czują, że muszą budować nieprzeniknione mury wokół swojego kodu. W silnie zakapsowanych językach, Jeśli API ma błąd i zorientowałeś się, co poszło nie tak, nadal możesz nie być w stanie obejść go, ponieważ potrzebna metoda jest szeregowy. W Pythonie postawa brzmi: "pewnie". Jeśli myślisz, że rozumiesz sytuację, być może nawet ją przeczytałeś, to wszystko, co możemy powiedzieć, to " powodzenia!".

Pamiętaj, hermetyzacja nie jest nawet słabo związana z "bezpieczeństwem", czy trzymaniem dzieci z dala od trawnika. Jest to kolejny wzorzec, który powinien być użyty, aby ułatwić zrozumienie bazy kodu.

 186
Author: Thomas Ahle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-08 07:15:50

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

Ściśle mówiąc, prywatne metody są dostępne poza ich klasą, tylko trudno dostępne. Nic w Python jest naprawdę prywatny; wewnętrznie, nazwy metod prywatnych i atrybuty są zniekształcone i niezmieszane w locie, aby sprawiały wrażenie niedostępne po ich imionach. Ty może uzyskać dostęp do metody _ _ parse Klasa MP3FileInfo wg nazwy _ MP3FileInfo_ _ parse. Przyznaj, że jest to interesujące, a następnie obiecaj, że nigdy, przenigdy nie rób tego prawdziwym szyfrem. Prywatne metody są prywatne dla rozumu, ale jak wiele innych rzeczy w Python, ich prywatność jest ostatecznie kwestia konwencji, nie Siła.

 146
Author: xsl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 09:03:45

Często używanym zwrotem jest "wszyscy zgadzamy się na dorosłych tutaj". Poprzez dodanie pojedynczego podkreślenia (nie narażaj) lub podwójnego podkreślenia (Ukryj), informujesz użytkownika swojej klasy, że chcesz, aby członek był w jakiś sposób "prywatny". Ufasz jednak, że wszyscy inni zachowują się odpowiedzialnie i szanują to, chyba że mają przekonujący powód, aby tego nie robić (np. debuggery, uzupełnianie kodu).

Jeśli naprawdę musisz mieć coś, co jest prywatne, to możesz to zaimplementować w rozszerzenie (np. w C Dla CPython). W większości przypadków Jednak po prostu uczysz się Pythonicznego sposobu robienia rzeczy.

 94
Author: Tony Meyer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 09:33:18

To nie jest tak, że absolutnie nie można ominąć szeregów w dowolnym języku (arytmetyka wskaźników w C++, odbicia w. NET/Java).

Chodzi o to, że pojawia się błąd, jeśli przez przypadek spróbujesz wywołać metodę prywatną. Ale jeśli chcesz strzelić sobie w stopę, zrób to.

Edit: nie próbujesz zabezpieczyć swoich rzeczy przez oo-enkapsulację, prawda?

 33
Author: Maximilian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 09:04:57

Konwencja nazewnictwa class.__stuff pozwala programiście wiedzieć, że nie jest przeznaczony do dostępu __stuff z zewnątrz. Nazwa mangling sprawia, że jest mało prawdopodobne, aby ktoś zrobił to przez przypadek.

To prawda, nadal możesz to obejść, jest to nawet łatwiejsze niż w innych językach (co BTW też ci na to pozwala), ale żaden programista Pythona nie zrobiłby tego, gdyby dbał o enkapsulację.

 12
Author: Nickolay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 09:05:52

Podobne zachowanie występuje, gdy nazwy atrybutów modułów zaczynają się od pojedynczego podkreślenia (np. _foo).

Atrybuty modułu nazwane jako takie nie będą kopiowane do modułu importującego przy użyciu metody from*, np.:

from bar import *
Jest to jednak konwencja, a nie ograniczenie językowe. Nie są to atrybuty prywatne; mogą być odwoływane i manipulowane przez każdego importera. Niektórzy twierdzą, że z tego powodu Python nie może zaimplementować prawdziwej enkapsulacji.
 12
Author: Ross,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-17 04:29:45

To tylko jedna z tych opcji projektowania języka. Na pewnym poziomie są one uzasadnione. Robią to tak, że trzeba iść dość daleko na swój sposób, aby spróbować i zadzwonić do metody, a jeśli naprawdę potrzebujesz go tak bardzo, musisz mieć całkiem dobry powód!

Debugowanie hooków i testowanie przychodzą na myśl jako możliwe aplikacje, używane oczywiście odpowiedzialnie.

 12
Author: ctcherry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-08 07:14:31

Ważna aktualizacja (Python 3.4):

Każdy identyfikator formularza __name (co najmniej dwa początkowe podkreślniki, co najwyżej jeden końcowy podkreślnik) jest publicznie zastępowany przez _classname__name, Gdzie classname jest bieżącą nazwą klasy z usuniętym głównym podkreślnikiem (- ami).

Dlatego {[1] } jest prywatny, podczas gdy {[2] } jest publiczny.

Https://docs.python.org/3/tutorial/classes.html#tut-private

Przykład

class Cat:
    def __init__(self, name='unnamed'):
        self.name = name
    def __print_my_name(self):
        print(self.name)
        
        
tom = Cat()
tom.__print_my_name() #Error
tom._Cat__print_my_name() #Prints name
 6
Author: Moradnejad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-24 11:16:38

W Pythonie 3.4 jest to zachowanie:

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

Zauważ, że reguły mangling są zaprojektowane głównie po to, aby uniknąć wypadków; nadal można uzyskać dostęp lub zmodyfikować zmienną, która jest uważana za prywatną. może to być nawet przydatne w szczególnych okolicznościach, takich jak debugger.

Nawet jeśli pytanie jest stare, mam nadzieję, że mój fragment może być pomocny.

 4
Author: Alberto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-08 07:17:09

Najważniejszą troską o prywatne metody i atrybuty jest mówienie programistom, aby nie wywoływali jej poza klasą i jest to enkapsulacja. można źle zrozumieć zabezpieczenie przed hermetyzacją. kiedy celowo używa się składni w ten sposób(poniżej), o której wspomniałeś, nie chcesz enkapsulacji.

obj._MyClass__myPrivateMethod()

Przeniosłem się z C# i na początku było to dla mnie dziwne, ale po jakimś czasie doszedłem do wniosku, że tylko sposób, w jaki projektanci kodu Pythona myślą o OOP jest inny.

 3
Author: Afshin Amiri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-26 22:37:29

Dlaczego 'prywatne' metody Pythona nie są tak naprawdę prywatne?

Jak rozumiem, oni nie mogą być prywatni. Jak można egzekwować prywatność?

Oczywistą odpowiedzią jest "Private members can only be accessed through self", ale to by nie zadziałało - self nie jest czymś wyjątkowym w Pythonie, jest niczym więcej niż powszechnie używaną nazwą dla pierwszego parametru funkcji.

 1
Author: user200783,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-14 10:15:52