Definiowanie funkcji modułów prywatnych w Pythonie

Zgodnie z http://www.faqs.org/docs/diveintopython/fileinfo_private.html :

Jak większość języków, Python ma pojęcie elementów prywatnych:

  • Private funkcje, których nie można wywołać z poza ich modułem

Jeśli jednak zdefiniuję dwa pliki:

#a.py
__num=1

I:

#b.py
import a
print a.__num

Kiedy uruchamiam b.py wyświetla 1 bez podania żadnego wyjątku. Czy diveintopython się myli, czy ja źle mnie zrozumiałeś? Czy jest jakiś sposób, aby zdefiniować funkcję modułu jako prywatną?

Author: olamundo, 2009-10-10

8 answers

W Pythonie "prywatność" zależy od poziomu" zgody dorosłych " - nie możesz tego wymusić (tak samo jak w prawdziwym życiu; -). Pojedynczy główny podkreślnik oznacza, że nie jesteś przypuszczalny , aby uzyskać do niego dostęp "z zewnątrz" -- dwa wiodące podkreślniki (bez końcowych podkreślników) niosą wiadomość jeszcze silniej... ale w końcu to nadal zależy od konwencji społecznej i konsensusu: introspekcja Pythona jest na tyle silna, że nie możesz kajdanki każdy inny programista na świecie, aby uszanować Twoje życzenia.

((Btw, choć jest to ściśle tajne, podobnie jest w C++: w większości kompilatorów, prosta linia #define private public przed #includeing .h Plik jest wszystkim, czego potrzeba sprytnym koderom, aby hash Twojej "prywatności"...!-))

 231
Author: Alex Martelli,
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-11-08 21:55:15

Może dojść do nieporozumień między Klasa privates oraz moduł privates.

A moduł prywatny zaczyna się od jeden podkreślnik
Taki element nie jest kopiowany wzdłuż, gdy używa się formy from <module_name> import * polecenia import; jest jednak importowany, jeśli używa się składni import <moudule_name> (zobacz odpowiedź Bena Wilhelma )
Po prostu usuń jeden podkreślnik z liczby a.__przykładu pytania i nie będzie widoczny w modułach, które importują a.py używając składni from a import *.

A Klasa prywatna zaczyna się od dwóch podkreślników (aka dunder czyli d-ouble under-score)
Taka zmienna ma swoją nazwę "mangled"aby zawierać nazwę klasy itd.
Nadal można do niego uzyskać dostęp poza logiką klasy, poprzez zniekształconą nazwę.
Chociaż nazwa mangling może służyć jako łagodne urządzenie zapobiegające nieautoryzowanemu dostępowi, jej głównym celem jest zapobieganie ewentualnym kolizjom nazw z członkami klasy przodka klasy. Zobacz zabawne, ale dokładne odniesienie Alexa Martellego do zgodnych dorosłych , jak opisuje konwencję stosowaną w odniesieniu do tych zmiennych.

>>> class Foo(object):
...    __bar = 99
...    def PrintBar(self):
...        print(self.__bar)
...
>>> myFoo = Foo()
>>> myFoo.__bar  #direct attempt no go
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__bar'
>>> myFoo.PrintBar()  # the class itself of course can access it
99
>>> dir(Foo)    # yet can see it
['PrintBar', '_Foo__bar', '__class__', '__delattr__', '__dict__', '__doc__', '__
format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__
', '__subclasshook__', '__weakref__']
>>> myFoo._Foo__bar  #and get to it by its mangled name !  (but I shouldn't!!!)
99
>>>
 222
Author: mjv,
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
2016-09-07 18:27:02

To pytanie nie zostało w pełni wyjaśnione, ponieważ prywatność modułu nie jest czysto konwencjonalna, a ponieważ użycie import może lub nie może rozpoznać prywatności modułu, w zależności od tego, jak jest używana.

Jeśli zdefiniujesz nazwy prywatne w module, nazwy te zostaną zaimportowane do dowolnego skryptu używającego składni "Importuj nazwę_modułu". Tak więc, zakładając, że poprawnie zdefiniowałeś w swoim przykładzie moduł private, _num, w a.py w ten sposób..

#a.py
_num=1

..będziesz mógł uzyskać dostęp it in b.py z symbolem nazwy modułu:

#b.py
import a
...
foo = a._num # 1

Aby importować tylko nie-prywatne z a.py, musisz użyć z składnia:

#b.py
from a import *
...
foo = _num # throws NameError: name '_num' is not defined

Dla jasności, jednak lepiej jest być wyraźnym podczas importowania nazw z modułów, niż importować je wszystkie z'*':

#b.py
from a import name1 
from a import name2
...
 66
Author: Ben Wilhelm,
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
2012-11-29 03:50:32

Python pozwala na prywatne klasy z podwójnym prefiksem podkreślenia. Ta technika nie działa na poziomie modułu, więc myślę, że jest to błąd w nurkowaniu w Pythonie.

Oto przykład funkcji klas prywatnych:

class foo():
    def bar(self): pass
    def __bar(self): pass

f = foo()
f.bar()   # this call succeeds
f.__bar() # this call fails
 28
Author: Andrew Hare,
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
2009-10-10 05:46:31

Jest to starożytne pytanie, ale zmienne zniekształcone w module private (jeden podkreślnik) I class-private (dwa podkreślniki) są teraz objęte standardową dokumentacją:

Samouczek Pythona "Klasy " Zmienne Prywatne

 1
Author: user1338062,
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-09-14 09:26:39

Możesz dodać wewnętrzną funkcję:

def public(self, args):
   def private(self.root, data):
       if (self.root != None):
          pass #do something with data
Coś takiego, jeśli naprawdę potrzebujesz takiego poziomu prywatności.
 1
Author: Ilian Zapryanov,
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-03-30 12:43:43

Wbudowany z zamknięciami lub funkcjami jest jednokierunkowy. Jest to powszechne w JS, chociaż nie jest wymagane dla platform innych niż przeglądarki lub pracowników przeglądarki.

W Pythonie wydaje się to trochę dziwne, ale jeśli coś naprawdę musi być ukryte, może to być sposób. Co więcej, używanie API Pythona i przechowywanie rzeczy, które wymagają ukrycia w języku C (lub innym języku), jest prawdopodobnie najlepszym sposobem. W przeciwnym razie poszedłbym na umieszczenie kodu wewnątrz funkcji, wywołanie go i posiadanie go zwróć elementy, które chcesz wyeksportować.

 0
Author: Martian Fame,
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-01-14 11:25:00

Python ma trzy tryby via., prywatne, publiczne i chronione .Podczas importowania modułu dostępny jest tylko tryb publiczny .tak więc prywatne i chronione Moduły nie mogą być wywoływane poza modułem, np. podczas importowania .

 -5
Author: sravan,
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
2016-06-18 08:40:48