Klasa "prywatna" (implementacja) w Pythonie

Koduję mały moduł Pythona składający się z dwóch części:

  • niektóre funkcje definiujące publiczny interfejs,
  • Klasa implementacyjna używana przez powyższe funkcje, ale nie mająca znaczenia poza modułem.

Na początku zdecydowałem się "ukryć" tę klasę implementacji, definiując ją wewnątrz funkcji używając jej, ale to utrudnia czytelność i nie może być użyte, jeśli wiele funkcji używa ponownie tej samej klasy.

Więc oprócz komentarzy i docstrings, czy istnieje mechanizm oznaczający klasę jako "prywatną " lub"wewnętrzną"? Znam mechanizm podkreślenia, ale jak rozumiem, dotyczy to tylko zmiennych, funkcji i nazw metod.

Author: 200_success, 2009-02-15

7 answers

Użyj pojedynczego przedrostka podkreślenia:

class _Internal:
    ...

Jest to oficjalna Konwencja Pythona dla' wewnętrznych 'symboli;" from module import * " nie importuje obiektów z prefiksem podkreślenia.

Edit: odniesienie do konwencji pojedynczego podkreślenia

 134
Author: Ferdinand Beyer,
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-11-11 00:06:56

W skrócie:

  1. Nie możesz egzekwować prywatności . W Pythonie nie ma prywatnych klas/metod/funkcji. Przynajmniej nie ścisła prywatność, jak w innych językach, takich jak Java.

  2. Możesz tylko wskazać/zasugerować prywatność . Jest to zgodne z konwencją. Konwencja Pythona dotycząca oznaczania klasy/funkcji/metody jako prywatnej polega na poprzedzaniu jej znakiem _ (podkreślenie). Na przykład, def _myfunc() LUB class _MyClass:. Możesz również utworzyć pseudo-prywatność, wprowadzając metodę z dwoma podkreślnikami (np.: __foo). Nie można uzyskać dostępu do metody bezpośrednio, ale nadal można ją wywołać przez specjalny prefiks używając nazwy klasy(np: _classname__foo). Najlepsze, co możesz zrobić, to wskazać / zasugerować prywatność, a nie egzekwować ją.

Python jest pod tym względem jak perl. Parafrazując słynny tekst o prywatności z książki Perla, filozofia jest taka, że powinieneś trzymać się z dala od salonu, ponieważ nie byłeś zaproszony, a nie dlatego, że jest broniony strzelbą.

Dla więcej informacji:

 53
Author: Karl Fast,
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-06-21 13:49:50

Zdefiniuj __all__, listę nazw, które chcesz wyeksportować (zobacz dokumentację ).

__all__ = ['public_class'] # don't add here the 'implementation_class'
 35
Author: UncleZeiv,
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-02-15 15:36:03

Wzór, który czasami używam jest taki:

Define a class:

class x(object):
    def doThis(self):
        ...
    def doThat(self):
        ...

Tworzy instancję klasy, nadpisując nazwę klasy:

x = x()

Zdefiniuj symbole eksponujące funkcjonalność:

doThis = x.doThis
doThat = x.doThat

Usuń samą instancję:

del x

Teraz masz moduł, który ujawnia tylko twoje publiczne funkcje.

 9
Author: theller,
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-02-15 15:58:49

Konwencja jest poprzedzona znakiem " _ " do klas wewnętrznych, funkcji i zmiennych.

 7
Author: Benjamin Peterson,
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-02-15 15:33:48

Aby zająć się kwestią konwencji projektowych, i jak powiedział Christopher, naprawdę nie ma czegoś takiego jak" prywatne " w Pythonie. Może to zabrzmieć dziwnie, jak na kogoś, kto pochodzi z C / C++ (jak ja jakiś czas temu), ale w końcu pewnie zdasz sobie sprawę, że przestrzeganie konwencji wystarczy.

Zobaczenie czegoś z podkreśleniem z przodu powinno być wystarczająco dobrą wskazówką, aby nie używać tego bezpośrednio. Jeśli interesuje Cię zaśmiecanie help(MyClass) wyjścia (na które wszyscy patrzą, gdy szukając, jak używać klasy), podkreślone atrybuty / klasy nie są tam zawarte, więc skończysz po prostu mając opisany "publiczny" interfejs.

Plus, posiadanie wszystkiego, co publiczne, ma swoje niesamowite plusy, na przykład, możesz testować jednostki praktycznie wszystko z zewnątrz (czego nie możesz zrobić z C/C++ private constructs).

 4
Author: Dimitri Tcaciuc,
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-02-15 18:09:59

Użyj dwóch podkreślników, aby przedrostki nazw" prywatnych " identyfikatorów. Dla klas w module, użyj pojedynczego podkreślnika wiodącego i nie będą one importowane za pomocą "from module import *".

class _MyInternalClass:
    def __my_private_method:
        pass

(nie ma czegoś takiego jak prawdziwe "prywatne" w Pythonie. Na przykład Python automatycznie zmienia nazwy członków klasy z podwójnymi podkreślnikami na __clssname_mymember. Tak naprawdę, jeśli znasz zniekształconą nazwę, możesz użyć podmiotu "prywatnego" i tak. Zobacz tutaj. i oczywiście możesz wybrać aby ręcznie zaimportować klasy "wewnętrzne", jeśli chcesz).

 2
Author: chroder,
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-02-15 19:59:45