Модуль Python: 'Private' в пакете
У меня есть пакет mypack
с модулями mod_a
и mod_b
. Я сам намерен сам пакет и mod_a
импортировать:
import mypack
import mypack.mod_a
Однако я хотел бы сохранить mod_b
для эксклюзивного использования mypack
. Это потому, что существует просто для организации последнего внутреннего кода.
Мой первый вопрос: есть ли принятая практика в программировании на Python иметь модули 'private', подобные этому?
Если да, то мой второй вопрос: какой лучший способ передать это намерение клиенту? Я префикс имени с подчеркиванием (т.е. _mod_b
)? Или было бы неплохо объявить подпакет private
и разместить там все такие модули?
Ответы
Ответ 1
Решение, на котором я остановился, - создать подпакет 'private' и поместить все модули, которые я хочу скрыть там. Таким образом, они остаются убранными, оставляя mypack
список модулей чище и легче разбираться.
Для меня это тоже не выглядит неряшливым.
Ответ 2
I префикс частных модулей с подчеркиванием для передачи намерения пользователю. В вашем случае это будет mypack._mod_b
Это в том же духе (но не полностью аналогичном) рекомендации PEP8 для обозначения модулей расширения C с лидирующим подчеркиванием при его завершении модулем Python; т.е. _socket
и socket
.
Ответ 3
Пока нет явных закрытых ключевых слов, существует соглашение о том, что частные функции начинаются с одного символа подчеркивания, но двузначный знак подчеркивания сделает его таким, чтобы другие не могли легко вызвать функцию извне модуля. Смотрите 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
.
Ответ 4
Python не строго знает или поддерживает "private" или "защищенные" методы или классы. Там есть соглашение о том, что методы с префиксом одного подчеркивания не являются частью официального API, но я бы не делал этого по классам или файлам - это уродливо.
Если кто-то действительно нуждается в подклассе или доступе к mod_b, зачем ему это мешает? Вы всегда можете указать предпочтительный API в своей документации и документе в своем модуле, к которому вы не должны обращаться напрямую, и вместо этого используйте mypack.
Ответ 5
В этом сценарии нужно учитывать одну вещь - косвенный импорт. Если в 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
, где все, что может иметь любые "модификаторы доступа", по вашему желанию - пользователи будут знать, что есть драконы