我有一个mypack
个包,其中包含模块mod_a
和mod_b
。我打算将包本身和mod_a
自由导入:
import mypack
import mypack.mod_a
但是,我想mod_b
仅限mypack
使用_mod_b
。那是因为它的存在仅仅是为了组织后者的内部代码。
我的第一个问题是,在Python编程中接受这样的'私有'模块是否是公认的做法?
如果是,我的第二个问题是,向客户传达这一意图的最佳方式是什么?我是否在名称前加下划线(即private
)?或者声明一个子包{{1}}并将所有这些模块放在那里是个好主意吗?
答案 0 :(得分:32)
我使用下划线为私有模块添加前缀,以将意图传达给用户。在您的情况下,这将是mypack._mod_b
这与PEP8的建议完全相同(但并不完全类似),当C-extension模块被Python模块包装时,它将C-extension模块命名为前导下划线;即_socket
和socket
。
答案 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
包中,其中的任何内容都可以带有您喜欢的任何“访问修饰符”-用户将知道有龙