2010-08-30 72 views
22

我有一个包mypack,其中包含模块mod_amod_b。我打算在包本身,mod_a自由地输入:Python:包中的'Private'模块

import mypack 
import mypack.mod_a 

不过,我想继续mod_b独家使用的mypack。这是因为它仅仅是为了组织后者的内部代码而存在。

我的第一个问题是,在Python编程中有一个公认的做法是拥有这样的“私有”模块吗?

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

回答

13

我已经解决的解决方案是创建一个子包“私人”,并将所有模块我想隐藏在那里。通过这种方式,他们保持收起状态,使mypack的模块列表更清晰并且更易于解析。

对我而言,这看起来并不平庸。

+0

我将在近6年后发布这篇文章,提供与您相同的问题和动机。私人子包方法仍然是你采取的方法还是你从那以后尝试了其他方法? – 2016-06-29 21:59:10

+2

是的。我仍然在使用这种方法。还没有找到更好的选择。 – 2016-07-07 05:45:46

+3

感谢您的更新,并首先提出了这种方法。我在“private”子包名称前添加一个'z_',以便它在IDE代码完成下拉菜单中最后显示。我在子包的'__init __。py'中使用相对导入来仅公开“公共”函数。在PyCharm和Jupyter中,为了保持内部模块的名称不超出下拉列表,每个模块必须具有与模块名称相同的函数,并且必须将该函数导入到__init __。py中。你可能已经知道所有这些,但如果不是这样的话。如果你想让我扩大为答案,请让我知道。 – 2016-07-07 15:16:39

2

Python并不严格知道或支持“私有”或“受保护的”方法或类。有一个约定,前缀为单个下划线的方法不是官方API的一部分,但我不会在类或文件上执行此操作 - 这很丑陋。

如果有人真的需要继承或访问mod_b,为什么要阻止他/她这样做?您始终可以在文档中提供首选API,并在模块中记录您不应直接访问它并使用mypack替代。

+3

我可以像'mod_a'一样访问'mod_b'。但是,假设有20个模块类似于'mod_b'。因此,当客户端在编辑器中输入'mypack.'时,智能感知将列出全部25个私有模块和公共模块。这会让我的代码更难以探索。这就是我想“隐藏”那些不适合客户端的模块的原因。至于文件,人们通常更喜欢探索阅读文件。 – 2010-08-31 17:22:57

+0

正如Matt Joiner所说,不要将'mod_b'导入你的'__init __。py'。我建议你也查看'__all__'特殊变量。如果这些工作都没有完成,问题出在Intellisense上。 – ssokolow 2010-09-04 21:33:30

+3

ssokolow,请参阅Matt的回答下的第三条评论。即使在'mypack/__ init __。py'中未导入mod_b',在客户端代码中输入'import mypack.mod_b'仍然可以成功。这是因为Python不需要将嵌入式模块导入顶级导入模块(例如'mypack.mod_b')以进行工作。 – 2010-09-05 06:24:29

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文件。

+4

Aterrel,你的意思是“不包含在'__init __。py'”中?是否不要在'__init __。py'中放置语句'import mod_b'?如果是这样,那仍然不能解决我的问题。客户端仍然可以像公共模块一样导入'mod_b':import mypack.mod_b'。或者你的意思是别的吗? – 2010-08-31 16:44:09

+1

因此,它不会严格执行该模块是私人的,就像单个下划线很弱。但是如果没有明确地导入它,它就不会显示出来,这仍然非常私密。我想你可以用两个主要的下划线来命名文件,但我从来没有玩过这个。 – aterrel 2010-09-01 03:17:36

+1

感谢您的答复。我正在解决的解决方案是在'mypack'下创建一个'private'子包,并将所有模块都放在'隐藏'中。这有助于我更轻松地探索代码(例如通过智能感知),将所有未被充分利用的绒毛都去掉。 – 2010-09-02 06:20:11

21

我用一个下划线前缀私有模块将意图传达给用户。在你的情况下,这将是mypack._mod_b

这与PEP8的建议相同(但不完全类似),当它被Python模块包装时,用带有下划线的名称命名C扩展模块;即_socketsocket