Python: "Частный" модуль в пакете

У меня есть посылка mypack с модулями mod_a а также mod_b в этом. Я намерен сам пакет и mod_a свободно ввозиться:

import mypack
import mypack.mod_a

Тем не менее, я хотел бы сохранить mod_b для исключительного использования mypack, Это потому, что он существует просто для организации внутреннего кода последнего.

Мой первый вопрос: является ли общепринятой практикой в ​​программировании на Python иметь такие "частные" модули?

Если да, мой второй вопрос: как лучше донести это намерение до клиента? Должен ли я ставить перед именем подчеркивание (т.е. _mod_b)? Или было бы неплохо объявить подпакет private и разместить все такие модули там?

4 ответа

Решение

Решение, на котором я остановился, заключается в создании подпакета "private" и размещении там всех модулей, которые я хочу скрыть. Таким образом, они остаются убранными, оставляя mypackСписок модулей чище и проще для разбора.

Для меня это тоже не выглядит пифоничным.

Я префикс частных модулей с подчеркиванием, чтобы сообщить намерение пользователю. В вашем случае это будет mypack._mod_b

Это в том же духе (но не полностью аналогично) рекомендации PEP8 называть модули расширения C с начальным подчеркиванием, когда оно заключено в модуль Python; т.е. _socket а также socket,

Хотя не существует явных закрытых ключевых слов, существует соглашение, согласно которому закрытые функции должны начинаться с одного подчеркивания, но двойное начальное подчеркивание сделает это таким образом, чтобы другие не могли легко вызвать функцию извне модуля. Смотрите следующее из PEP 8

- _single_leading_underscore: weak "internal use" indicator.  E.g. "from M
  import *" does not import objects whose name starts with an underscore.

- single_trailing_underscore_: used by convention to avoid conflicts with
  Python keyword, e.g.

  Tkinter.Toplevel(master, class_='ClassName')

- __double_leading_underscore: when naming a class attribute, invokes name
  mangling (inside class FooBar, __boo becomes _FooBar__boo; see below).

- __double_leading_and_trailing_underscore__: "magic" objects or
  attributes that live in user-controlled namespaces.  E.g. __init__,
  __import__ or __file__.  Never invent such names; only use them
  as documented.

Чтобы сделать весь модуль приватным, не включайте его __init__.py файл.

Одна вещь, о которой следует помнить в этом сценарии, - это косвенный импорт. Если вmypack ты

from mypack._mod_b import foo
foo()

Тогда пользователь может

from mypack import foo
foo()

и не будь мудрее. Я рекомендую импортировать как

from mypack import _mod_b
_mod_b.foo()

тогда пользователь сразу увидит красный флаг, когда попытается

from mypack import _mod_b

Что касается фактической структуры каталогов, вы можете даже расширить ответ Джереми на _package_of_this_kind пакет, где все, что может иметь любые "модификаторы доступа", которые вам нравятся - пользователи будут знать, что есть драконы

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

Если кому-то действительно нужно создать подкласс или получить доступ к mod_b, зачем мешать ему / ей делать это? Вы всегда можете предоставить предпочтительный API в своей документации и документе в своем модуле, чтобы вам не пришлось обращаться к нему напрямую и использовать mypack вместо него.

Другие вопросы по тегам