it-swarm-eu.dev

Proč nejsou Pythonovy „soukromé“ metody vlastně soukromé?

Python nám dává možnost vytvořit 'soukromé' metody a proměnné v rámci třídy přednastavením dvojitého podtržítka na jméno, jako je tento: __myPrivateMethod(). Jak to tedy můžeme vysvětlit

>>> 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 jde?!

Trochu to vysvětlím těm, kteří to tak docela nedostali.

>>> class MyClass:
...     def myPublicMethod(self):
...             print 'public method'
...     def __myPrivateMethod(self):
...             print 'this is private!!'
... 
>>> obj = MyClass()

To, co jsem tam dělal, je vytvořit třídu s veřejnou metodou a soukromou metodou a vytvořit instanci.

Dále nazývám jeho veřejnou metodu.

>>> obj.myPublicMethod()
public method

Dále se snažím volat jeho soukromou metodu.

>>> obj.__myPrivateMethod()
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: MyClass instance has no attribute '__myPrivateMethod'

Všechno vypadá dobře; nemůžeme to nazvat. Je to vlastně „soukromé“. Vlastně to tak není. Spuštění dir () na objektu odhalí novou magickou metodu, kterou python magicky vytvoří pro všechny vaše „soukromé“ metody.

>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']

Název této nové metody je vždy podtržítko, za nímž následuje název třídy následovaný názvem metody.

>>> obj._MyClass__myPrivateMethod()
this is private!!

Tolik k zapouzdření, co?

V každém případě jsem vždycky slyšel, že Python nepodporuje zapouzdření, tak proč to zkusit? Co dává?

557
willurd

Jméno scrambling se používá k zajištění toho, aby podtřídy ne náhodně nepředepisovaly soukromé metody a atributy jejich nadřazených tříd. Není navržen tak, aby zabránil úmyslnému přístupu zvenčí.

Například:

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

Samozřejmě, že se rozdělí, pokud dvě různé třídy mají stejný název.

524
Alya

Příklad soukromé funkce

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

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

Přísně řečeno, soukromé metody jsou Dostupné mimo jejich třídu, jen Nejsou snadno dostupné. Nic v Python není skutečně soukromé; interně, jména soukromých metod a atributy jsou zmatené a rozmělněné za letu, aby se zdály nepřístupné jejich jmény. Můžete přistupovat k metodě __parse třídy MP3FileInfo podle názvu _MP3FileInfo__parse. Uvědomte si, že je to zajímavé, pak slibujte Nikdy, nikdy to neučinte v reálném kódu. Soukromé metody jsou soukromé Důvody, ale jako mnoho jiných věcí v [.____. .] Python, jejich privatita je Nakonec záležitostí konvence, ne [.].

134
xsl

Fráze běžně používaná je "jsme všichni souhlasí dospělí zde". Přednastavením jediného podtržítka (nevystavujte) nebo dvojitým podtržítkem (skrýt) říkáte uživateli své třídy, že chcete, aby byl člen nějakým způsobem „soukromý“. Nicméně všem ostatním věříte, že se budou chovat odpovědně a respektovat, pokud nemají přesvědčivý důvod (např. Debugery, dokončení kódu).

Pokud opravdu musíte mít něco, co je soukromé, pak jej můžete implementovat v rozšíření (např. V C pro CPython). Ve většině případů se však jednoduše naučíte Pythonic způsobem, jak věci dělat.

86
Tony Meyer

Není to tak, že byste se absolutně nemohli obejít kolem privatity členů v jakémkoli jazyce (ukazatel aritmetiky v C++, Reflections in .NET/Java).

Jde o to, že pokud se pokusíte zavolat soukromou metodu náhodou, dostanete chybu. Pokud se však chcete střílet do nohy, pokračujte a udělejte to.

Edit: Nesnažíte se zabezpečit vaše věci OO-zapouzdřením, co?

32
Maximilian

Podobné chování existuje, když názvy atributů modulu začínají jedním podtržítkem (např. _Foo).

Atributy modulů pojmenované jako takové nebudou kopírovány do modulu pro import při použití metody from*, např .:

from bar import *

Jedná se však o konvenci a ne o jazykové omezení. Toto nejsou soukromé atributy; mohou být odkazovány a manipulovány jakýmkoli dovozcem. Někteří argumentují, že protože toto, Python nemůže realizovat skutečné zapouzdření.

12
Ross

Je to jen jeden z těch jazykových návrhů. Na určité úrovni jsou oprávněné. Dělají to tak, že musíte jít daleko daleko z cesty, abyste se pokusili zavolat metodu, a pokud to opravdu potřebujete, musíte mít dobrý důvod!

Ladění háčků a testování přicházejí v úvahu jako možné aplikace, které se používají zodpovědně.

12
ctcherry

Konvence pojmenování class.__stuff umožňuje programátorovi vědět, že nemá přístup k __stuff zvenku. Jméno mangling dělá to nepravděpodobný někdo bude dělat to náhodou.

Pravdou je, že stále můžete tento problém obejít, je to ještě jednodušší než v jiných jazycích (což vám BTW také umožňuje), ale žádný programátor Python by to neudělal, kdyby se staral o zapouzdření.

11
Nickolay

S Pythonem 3.4 je to chování:

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

Povšimněte si, že pravidla pro manipulaci jsou určena především k tomu, aby se zabránilo nehodám; je stále možné přistupovat nebo měnit proměnnou, která je považována za soukromou. To může být užitečné i za zvláštních okolností, například v debuggeru.

I když je otázka stará, doufám, že můj úryvek může být užitečný.

3
Alberto

Nejdůležitějším zájmem o soukromé metody a atributy je říci vývojářům, aby to neříkali mimo třídu a to je zapouzdření. člověk může nepochopit bezpečnost před zapouzdřením. když člověk úmyslně používá syntaxi, kterou jste uvedli, nechcete zapouzdřit.

obj._MyClass__myPrivateMethod()

Migroval jsem z C # a zpočátku to bylo pro mě také divné, ale po chvíli jsem přišel k myšlence, že jen způsob, jakým si Pythonový návrhář myslí OOP je jiný. 

2
Afshin Amiri

Proč nejsou Pythonovy „soukromé“ metody vlastně soukromé?

Jak tomu rozumím, nemůžebýt soukromý. Jak by mohlo být prosazováno soukromí?

Zřejmá odpověď je, že „soukromým členům lze přistupovat pouze prostřednictvím self“, ale to by nefungovalo - self není v Pythonu zvláštní, není to nic jiného než běžně používaný název prvního parametru funkce.

0
user200783