关于访问修饰符:python中的”private”(实现)类

“Private” (implementation) class in Python

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

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

首先,我决定通过在使用这个实现类的函数中定义它来"隐藏"这个实现类,但是这会妨碍可读性,并且如果多个函数重用同一个类,就不能使用这个实现类。

因此,除了注释和docstrings之外,是否还有一种机制将类标记为"private"或"internal"?我知道下划线机制,但据我所知,它只适用于变量、函数和方法名。


使用一个下划线前缀:

1
2
class _Internal:
    ...

这是"internal"符号的官方python约定;"from module import*"不导入带下划线的前缀对象。

编辑:对单个下划线惯例的引用


简而言之:

  • 你不能强制隐私。python中没有私有类/方法/函数。至少,像其他语言,如Java,不是严格的隐私。

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

  • 在这方面,python与perl类似。要从Perl的书中解释关于隐私的一句著名的话,其哲学是你应该远离起居室,因为你没有被邀请,而不是因为它是用猎枪保卫的。

    更多信息:

    • 私有变量python文档
    • 私人功能潜入Python,由马克·朝圣者设计
    • 为什么python的"private"方法实际上不是私有的?叠加溢出问题70528


    定义__all__,一个要导出的名称列表(参见文档)。

    1
    __all__ = ['public_class'] # don't add here the 'implementation_class'

    我有时使用的模式是:

    定义一个类:

    1
    2
    3
    4
    5
    class x(object):
        def doThis(self):
            ...
        def doThat(self):
            ...

    创建类的实例,重写类名:

    1
    x = x()

    定义公开功能的符号:

    1
    2
    doThis = x.doThis
    doThat = x.doThat

    删除实例本身:

    1
    del x

    现在您有了一个只公开公共功能的模块。


    该约定预先"_uuu"到内部类、函数和变量。


    为了解决设计约定的问题,正如克里斯托弗所说,在Python中实际上没有"私有"这样的东西。对于来自C/C++背景的人来说,这听起来有点扭曲(像我一样),但最终,你可能会意识到下面的约定已经足够了。

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

    另外,让所有的公共设备都有自己的优点,例如,你可以从外部测试几乎所有的东西(你不能用C/C++私有结构来做)。


    使用两个下划线为"private"标识符的名称加前缀。对于模块中的类,使用一个前导下划线,并且不会使用"从模块导入*"导入它们。

    1
    2
    3
    class _MyInternalClass:
        def __my_private_method:
            pass

    (在python中没有真正的"private"这样的东西。例如,python只是用双下划线自动管理类成员的名称,使其成为__clssname_mymember。所以说真的,如果你知道被破坏的名字,你无论如何都可以使用"私有"实体。请看这里。当然,如果您愿意的话,您可以选择手动导入"内部"类)。