2009-02-15 2 views
73

Я кодирования небольшой модуль Python, состоящий из двух частей:«Private» (реализация) класса в Python

  • некоторые функции, определяющие общий интерфейс,
  • класс реализации, используемый выше функций, но что не имеет смысла вне модуля.

Сначала я решил «скрыть» этот класс реализации, определив его внутри используемой функции, но это затрудняет читаемость и не может использоваться, если несколько функций повторно используют один и тот же класс.

Итак, в дополнение к комментариям и docstrings, есть ли механизм для обозначения класса как «частного» или «внутреннего»? Я знаю механизм подчеркивания, но, как я понимаю, он применяется только к именам переменных, функций и методов.

ответ

124

Используйте один подчеркивание префикс:

class _Internal: 
    ... 

Это официальная конвенция Python для 'внутренних' символов; «from module import *» не импортирует объекты с префиксами с подчеркиванием.

Edit: Ссылка на single underscore convention

+0

Я не KNO w правило подчеркивания распространяется на классы. Я не хочу загромождать свое пространство имен при импорте, поэтому это поведение - то, что я искал. Благодаря! – oparisy

+1

Поскольку вы заявляете, что это «официальное» соглашение на python, было бы неплохо со ссылкой. Другое сообщение здесь говорит, что __all__ является официальным способом и ссылается на документацию. – flodin

+9

http://www.python.org/dev/peps/pep-0008/ - _single_leading_underscore: слабый индикатор «внутреннего использования». Например. «from M import *» не импортирует объекты, имя которых начинается с подчеркивания. - Классы для внутреннего использования имеют ведущее подчеркивание. – Miles

7

Конвенция добавляет «_» к внутренним классам, функциям и переменным.

34

Определение __all__, список имен, которые вы хотите экспортировать (see documentation).

__all__ = ['public_class'] # don't add here the 'implementation_class' 
9

Шаблон, который я иногда использую это:

Определение класса:

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

Создать экземпляр класса, переписав имя класса:

x = x() 

Определите символы, которые раскрывают функциональные возможности:

doThis = x.doThis 
doThat = x.doThat 

Удалить экземпляру себя:

del x 

Теперь у вас есть модуль, который только выставляет свои общественные функции.

+0

это классно! –

+0

Потратил минутку, чтобы понять цель/функцию «переписывания имени класса», но я получил большую улыбку, когда я это сделал. Не уверен, когда я его буду использовать. :) –

2

Используйте два символа подчеркивания для префикса имен «частных» идентификаторов. Для классов в модуле используйте один знак подчеркивания, и они не будут импортироваться с помощью «из импорта модуля».

class _MyInternalClass: 
    def __my_private_method: 
     pass 

(Там нет такого понятия, как истинный «частный» в Python. Например, Python просто автоматически искажает имена членов класса с двойным подчеркиванием быть __clssname_mymember. Так что на самом деле, если вы знаете искаженное имя, которое вы может использовать «частную» сущность в любом случае. See here. И, конечно, вы можете вручную импортировать «внутренние» классы, если хотите).

+0

Почему два _? Одного достаточно. –

+0

Единственное подчеркивание является достаточным для предотвращения импорта из классов и функций импорта. Вам нужно два символа подчеркивания, чтобы вызвать функцию переключения имени Python. Должна быть яснее; Я редактировал. –

+0

Теперь, продолжение. Почему называют мангование? Какая возможная польза от этого? –

4

Чтобы решить проблему соглашений о дизайне, и, как сказал Кристофер, в Python действительно нет такой вещи, как «частный». Это может звучать круто для кого-то, исходящего из фона C/C++ (например, меня некоторое время назад), но в конце концов вы, вероятно, поймете, что следующие соглашения достаточно.

Увидеть что-то с подчеркиванием спереди должно быть достаточно хорошим намеком, чтобы не использовать его напрямую. Если вы заинтересованы в загромождении вывода help(MyClass) (на что все смотрят при поиске того, как использовать класс), подчеркнутые атрибуты/классы там не включаются, так что в итоге вы просто получите свой «общедоступный» интерфейс ,

Плюс, наличие у всех публики собственных впечатляющих привилегий, например, вы можете полностью тестировать что-либо извне (что вы не можете делать с частными конструкциями C/C++).

52

Короче:

  1. Вы не можете применять частную. В Python нет частных классов/методов/функций. По крайней мере, не строгая конфиденциальность, как на других языках, таких как Java.

  2. Вы можете указать или предложить конфиденциальность. Это следует за конвенцией. Соглашение python для маркировки класса/функции/метода как частного заключается в предисловии к нему с помощью символа _ (подчеркивание). Например, def _myfunc() или class _MyClass:. Вы также можете создать псевдо-конфиденциальность, предварительно используя метод с двумя символами подчеркивания (например: __foo). Вы не можете напрямую обращаться к этому методу, но вы все равно можете вызвать его через специальный префикс, используя имя класса (например: _classname__foo). Поэтому лучшее, что вы можете сделать, это указать/предложить конфиденциальность, а не обеспечивать ее соблюдение.

Python подобен perl в этом отношении. Перефразируя известную строку о конфиденциальности из книги Perl, философия состоит в том, что вы должны оставаться в гостиной, потому что вас не пригласили не потому, что она защищена дробовиком.

Для получения дополнительной информации:

+0

В ответ на # 1 вы можете обеспечить конфиденциальность методов. Использование двойного подчеркивания, такого как __method (self), сделает его недоступным вне класса. Но есть способ обойти его, называя его, как Foo() ._ Foo__method(). Думаю, это просто переименовывает его в нечто более эзотерическое. –

+1

Эта цитата точна. –

Смежные вопросы