Python:包中的“私有”模块

时间:2010-08-30 16:07:44

标签: python python-module

我有一个mypack个包,其中包含模块mod_amod_b。我打算将包本身和mod_a自由导入:

import mypack
import mypack.mod_a

但是,我想mod_b仅限mypack使用_mod_b。那是因为它的存在仅仅是为了组织后者的内部代码。

我的第一个问题是,在Python编程中接受这样的'私有'模块是否是公认的做法?

如果是,我的第二个问题是,向客户传达这一意图的最佳方式是什么?我是否在名称前加下划线(即private)?或者声明一个子包{{1}}并将所有这些模块放在那里是个好主意吗?

5 个答案:

答案 0 :(得分:32)

我使用下划线为私有模块添加前缀,以将意图传达给用户。在您的情况下,这将是mypack._mod_b

这与PEP8的建议完全相同(但并不完全类似),当C-extension模块被Python模块包装时,它将C-extension模块命名为前导下划线;即_socketsocket

答案 1 :(得分:12)

我已经确定的解决方案是创建一个子包'private'并将我希望隐藏的所有模块放在那里。通过这种方式,它们可以保存,使mypack的模块列表更清晰,更容易解析。

对我来说,这看起来也不是单声道。

答案 2 :(得分:6)

虽然没有明确的私有关键字,但有一个惯例是将私有函数从单个下划线开始,但是双前导下划线会使其他人无法轻易地从模块外部调用该函数。请参阅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文件。

答案 3 :(得分:2)

Python并不严格地了解或支持“私有”或“受保护”方法或类。有一种惯例,以单个下划线为前缀的方法不是官方API的一部分,但我不会在类或文件上执行此操作 - 这很难看。

如果有人确实需要子类或访问mod_b,为什么要阻止他/她这样做呢?您始终可以在文档中提供首选API,并在模块中提供不应直接访问它的文档,而是使用mypack。

答案 4 :(得分:0)

在这种情况下要注意的一件事是间接导入。如果您在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

对于实际的目录结构,您甚至可以将Jeremy的答案扩展到一个_package_of_this_kind包中,其中的任何内容都可以带有您喜欢的任何“访问修饰符”-用户将知道有龙