Python中的"私有"(实现)类

opa*_*isy 97 python access-modifiers

我正在编写一个由两部分组成的小型Python模块:

  • 一些定义公共接口的函数,
  • 上述函数使用的实现类,但在模块外部没有意义.

起初,我决定通过使用它在函数内部定义它来"隐藏"这个实现类,但这妨碍了可读性,如果多个函数重用同一个类,则不能使用它.

那么,除了评论和文档字符串之外,是否有一种机制将类标记为"私有"或"内部"?我知道下划线机制,但据我所知它只适用于变量,函数和方法名称.

Fer*_*yer 159

使用单个下划线前缀:

class _Internal:
    ...
Run Code Online (Sandbox Code Playgroud)

这是"内部"符号的官方Python约定; "from module import*"不会导入下划线前缀对象.

编辑:引用单个下划线约定

  • </div><h1 id="934962"></h1><div>我认为结构比地图更适合他的目的. (11认同)
  • 我不知道扩展到类的下划线规则.我不想在导入时混淆我的命名空间,所以这种行为就是我想要的.谢谢! (3认同)
  • 一个主要的下划线是将事物标记为内部的约定,"不要弄乱这个",而__all__更适用于设计用于"来自M import*"的模块,而不一定暗示模块用户不应该触摸那个班. (2认同)

Kar*_*ast 59

简而言之:

  1. 您无法强制执行隐私.Python中没有私有类/方法/函数.至少,不像其他语言那样严格的隐私,例如Java.

  2. 您只能表明/建议隐私.这符合一项惯例.将类/函数/方法标记为私有的python约定是以_(下划线)为前缀.例如,def _myfunc()class _MyClass:.您还可以通过使用两个下划线(例如::)为方法添加前缀来创建伪隐私__foo.您无法直接访问该方法,但您仍然可以使用classname通过特殊前缀来调用它(例如:) _classname__foo.因此,您可以做的最好的事情是表明/建议隐私,而不是强制执行.

在这方面,Python就像perl.从Perl书中解释一条关于隐私的着名路线,其理念是你应该离开起居室,因为你没有被邀请,而不是因为它是用霰弹枪进行辩护.

欲获得更多信息:

  • 作为对#1 的回应,您可以强制执行方法的隐私。使用像 __method(self) 这样的双下划线会使它在类之外无法访问。但是有一种方法可以通过调用它来解决它,例如 Foo()._Foo__method()。我想它只是将它重命名为更深奥的东西。 (2认同)

Unc*_*eiv 35

定义__all__要导出的名称列表(请参阅文档).

__all__ = ['public_class'] # don't add here the 'implementation_class'
Run Code Online (Sandbox Code Playgroud)

  • 这仅影响“from module import *”。您仍然可以像以前一样运行“from module import privatename”。 (5认同)

the*_*ler 10

我有时使用的模式是这样的:

定义一个类:

class x(object):
    def doThis(self):
        ...
    def doThat(self):
        ...
Run Code Online (Sandbox Code Playgroud)

创建类的实例,覆盖类名:

x = x()
Run Code Online (Sandbox Code Playgroud)

定义公开功能的符号:

doThis = x.doThis
doThat = x.doThat
Run Code Online (Sandbox Code Playgroud)

删除实例本身:

del x
Run Code Online (Sandbox Code Playgroud)

现在你有一个只暴露你的公共功能的模块.

  • 花了一分钟来理解“覆盖类名”的目的/功能,但是当我这样做时,我得到了一个大大的微笑。不知道什么时候会用到。:) (4认同)
  • 天啊,这真是一个黑客。请永远不要这样做。很酷 (4认同)
  • 这种技术有名字吗? (2认同)

Ben*_*son 8

该约定在内部类,函数和变量之前加上"_".


chr*_*der 6

使用两个下划线作为“私有”标识符名称的前缀。对于模块中的类,使用单个前导下划线,它们将不会使用“from module import *”导入。

class _MyInternalClass:
    def __my_private_method:
        pass
Run Code Online (Sandbox Code Playgroud)

(在 Python 中没有真正的“私有”这样的东西。例如,Python 只是自动将带有双下划线的类成员的名称修改为__clssname_mymember。因此,实际上,如果您知道经过修改的名称,则无论如何都可以使用“私有”实体.请参阅此处。当然,如果您愿意,您可以选择手动导入“内部”类)。

  • 可能的好处是烦扰需要访问这些变量的其他开发人员:) (6认同)

Dim*_*iuc 5

为了解决设计约定的问题,正如 Christopher 所说,Python 中确实没有“私有”这样的东西。对于来自 C/C++ 背景的人来说,这可能听起来有些扭曲(就像我之前的我),但最终,您可能会意识到遵循约定就足够了。

看到前面有下划线的东西应该是一个足够好的提示,不要直接使用它。如果您担心混乱的help(MyClass)输出(这是每个人在搜索如何使用类时都会看到的),下划线的属性/类不包括在内,因此您最终只会描述您的“公共”接口。

另外,将所有内容都公开有其独特的优势,例如,您可以从外部对几乎所有内容进行单元测试(而使用 C/C++ 私有构造则无法真正做到这一点)。