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

px9o7tmv  于 2023-01-08  发布在  Python
关注(0)|答案(8)|浏览(140)

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

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

起初,我决定通过在使用该类的函数内部定义它来“隐藏”这个实现类,但是这会妨碍可读性,并且如果多个函数重用同一个类,就不能使用它。
那么,除了注解和文档字符串之外,是否有一种机制可以将类标记为“private”或“internal”呢?我知道下划线机制,但据我所知,它只适用于变量、函数和方法名称。

7lrncoxx

7lrncoxx1#

使用单个下划线前缀:

class _Internal:
    ...

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

e5nszbig

e5nszbig2#

简而言之:
1.* * 你不能强制隐私**. Python中没有私有的类/方法/函数.至少,不像其他语言那样严格的隐私,比如Java.
1.* * 你只能指示/建议私有性**。这遵循一个约定。Python将一个类/函数/方法标记为私有的约定是在它前面加上_(下划线)。例如,def _myfunc()class _MyClass:。您还可以通过在方法前面加上两个下划线来创建伪隐私(例如,__foo)。您不能直接访问该方法,但是您仍然可以使用类名通过特殊前缀调用它(例如,_classname__foo)。因此,您所能做的最好是指示/建议隐私,而不是强制它。
Python在这方面就像Perl,套用Perl书中关于隐私的一句名言,其哲学是你应该远离客厅,因为你没有被邀请,而不是因为它是用猎枪来保护的。
如需了解更多信息:

zpf6vheq

zpf6vheq3#

定义__all__,这是要导出的名称列表(请参阅文档)。

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

hof1towb4#

我有时会使用这样一个模式:
定义类:

class x(object):
    def doThis(self):
        ...
    def doThat(self):
        ...

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

x = x()

定义显示功能的符号:

doThis = x.doThis
doThat = x.doThat

删除示例本身:

del x

现在您有了一个只公开公共函数的模块。

uinbv5nw

uinbv5nw5#

约定是在内部类、函数和变量前面加上“_”。

ghhaqwfi

ghhaqwfi6#

为了解决设计惯例的问题,正如chroder所说,Python中真的没有“private”这样的东西,这对于那些来自C/C背景的人来说可能听起来有点扭曲(就像我之前所说的),但是最终,你可能会意识到遵循惯例就足够了。
看到前面有下划线的东西应该是一个很好的提示,不要直接使用它。如果你担心混乱的help(MyClass)输出(这是每个人在搜索如何使用类时都会看到的),下划线的属性/类不包括在那里,所以你最终只需要描述你的“public”接口。
另外,所有东西都是公共的有它自己的好处,比如,你可以从外部单元测试几乎任何东西(你不能用C/C
私有结构来做)。

sd2nnvve

sd2nnvve7#

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

class _MyInternalClass:
    def __my_private_method:
        pass

(在Python中没有真正的“private”。例如,Python只是自动地将带有双下划线的类成员的名称变形为__clssname_mymember。所以,如果你知道变形后的名称,你就可以使用“private”实体。请看这里。当然,如果你愿意,你也可以选择手动导入“internal”类。)

ylamdve6

ylamdve68#

我是python新手,但据我所知,python不像java。下面是python中发生的情况:
班级学生:

__schoolName = 'XYZ School'      # private attribute
def __nameprivamethod(self):     # private function 
     print('two underscore')

班级学生:

_schoolName = 'XYZ School'       # protected attribute

我希望它能帮上忙,不要检查如何访问隐私和受保护的部分。

相关问题