Python 中的 “私有”(实现)类

2024-08-01 14:16:33 浏览数 (3)

在 Python 中,尽管没有严格意义上的私有类(private class),但可以通过命名约定和语言特性来模拟实现类似的访问控制。Python 的私有类的概念通常是通过以下几种方式来实现:

1、问题背景

我正在编码一个由两部分组成的小型 Python 模块:定义公共接口的一些函数,上述函数使用的实现类,但在模块外部没有意义。

起初,我决定通过在使用它的函数中定义实现类来“隐藏”它,但这阻碍了可读性,并且如果多个函数重用同一个类,则无法使用。

因此,除了注释和文档字符串之外,是否有一种机制可以将类标记为“私有”或“内部”?我知道下划线机制,但据我了解,它只适用于变量、函数和方法名称。

2、解决方案

答案 1:

使用单个下划线前缀:

代码语言:javascript复制
class _Internal:
    ...

这是 Python 中“内部”符号的官方约定;“from module import *”不会导入以 下划线为前缀的对象。

答案 2:

简而言之:

您无法强制执行隐私。Python 中没有私有类/方法/函数。至少不是像 Java 等其他语言中的严格隐私。

您只能指示/建议隐私。这遵循惯例。将类/函数/方法标记为私有的 Python 约定是在其前面加下划线 ()。例如,def _myfunc() 或 class _MyClass:。您还可以通过在方法前加两个下划线来创建伪隐私(例如,__foo)。您无法直接访问该方法,但仍可以通过使用类名前缀(例如,classname__foo)调用它。因此,您所能做的最好的事情是指示/建议隐私,而不是强制执行它。

Python 在这方面类似于 Perl。用 Perl 书中关于隐私的一句名言来解释,其理念是您应该待在客厅外,因为您没有被邀请,而不是因为它是用猎枪捍卫的。

答案 3:

定义 all,即您要导出的名称列表(请参阅文档)。

代码语言:javascript复制
__all__ = ['public_class'] # don't add here the 'implementation_class'

答案 4:

我有时使用的模式如下:

定义一个类:

代码语言:javascript复制
class x(object):
    def doThis(self):
        ...
    def doThat(self):
        ...

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

代码语言:javascript复制
x = x()

定义公开功能的符号:

代码语言:javascript复制
doThis = x.doThis
doThat = x.doThat

删除实例本身:

代码语言:javascript复制
del x

现在,您有一个仅公开公共函数的模块。

答案 5:

惯例是在内部类、函数和变量前加上“_”。

答案 6:

为了解决设计约定问题,正如 chroder 所说,Python 中实际上没有“私有”的概念。对于来自 C/C 背景的人(比如我一段时间前)来说,这听起来可能很扭曲,但最终,您可能会意识到遵守约定就足够了。

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

此外,公开所有内容都有其自身的优势,例如,您可以从外部单元测试几乎所有内容(在 C/C 私有构造中,您无法真正做到这一点)。

答案 7:

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

代码语言:javascript复制
class _MyInternalClass:
    def __my_private_method:
        pass

(Python 中没有真正的“私有”。例如,Python 只是自动将类成员的名称混淆为 __clssname_mymember 为双下划线。因此,只要您知道混淆的名称,您就可以使用“私有”实体。请参阅此处。当然,如果您愿意,可以选择手动导入“内部”类)。

0 人点赞