Python在类中是否具有“私有”变量?

我的未来我决定 提交于 2020-02-28 02:58:57

我来自Java世界,正在阅读Bruce Eckels的Python 3 Patterns,Recipes和Idioms

在阅读类时,它继续说在Python中,无需声明实例变量。 您只需在构造函数中使用它们,然后它们就在那里。

因此,例如:

class Simple:
    def __init__(self, s):
        print("inside the simple constructor")
        self.s = s

    def show(self):
        print(self.s)

    def showMsg(self, msg):
        print(msg + ':', self.show())

如果是这样,那么Simple类的任何对象都可以在类外部更改变量s的值。

例如:

if __name__ == "__main__":
    x = Simple("constructor argument")
    x.s = "test15" # this changes the value
    x.show()
    x.showMsg("A message")

在Java中,我们已经学会了有关公共/私有/保护变量的知识。 这些关键字之所以有意义,是因为有时您需要一个类中的变量,而该类之外的任何人都无法访问该变量。

为什么在Python中不需要这样做?


#1楼

我唯一使用私有变量的时间是在写入或读取变量时需要做其他事情时,因此需要强制使用setter和/或getter。

如前所述,这再次涉及文化。 我一直在从事免费阅读和编写其他类变量的项目。 一个实现被弃用时,识别使用该功能的所有代码路径的时间要长得多。 当强制使用setter和getter时,可以很容易地编写一条调试语句来识别已调用了不赞成使用的方法以及调用该方法的代码路径。

当您在任何人都可以编写扩展的项目上时,通知用户有关已弃用的方法的信息,这些方法将在几个发行版中消失,因此对于将升级时模块的损坏降至最低至关重要。

所以我的答案是; 如果您和您的同事维护一个简单的代码集,那么保护类变量并非总是必要的。 如果您正在编写一个可扩展的系统,那么对核心进行的更改就变得势在必行,而所有的扩展都需要使用代码来捕获这些更改。


#2楼

Python通过自动将类名添加到以两个下划线开头的任何标识符的功能,对私有标识符的支持有限。 在大多数情况下,这对程序员是透明的,但是最终结果是,以此方式命名的任何变量都可以用作私有变量。

有关更多信息,请参见此处

通常,与其他语言相比,Python的面向对象的实现有点原始。 但实际上,我很喜欢。 从概念上讲,这是一种非常简单的实现,非常适合该语言的动态样式。


#3楼

这是文化的。 在Python中,您无需写入其他类的实例或类变量。 在Java中,如果您确实想做的话,不会阻止您做同样的事情-毕竟,您始终可以编辑类本身的源代码来实现相同的效果。 Python放弃了这种安全性的幌子,并鼓励程序员负责。 实际上,这非常好用。

如果出于某种原因要模拟私有变量,则始终可以使用PEP 8中__前缀。 Python __foo诸如__foo之类的变量名称进行__foo以使它们在包含它们的类之外的代码中不易被看到(尽管只要有足够的决心,您可以解决它,就像您在工作时可以解决Java的保护一样。它)。

按照相同的约定, 即使没有从技术上阻止您这样做_前缀也意味着不要离开 。 您不会玩弄另一个类的变量__foo_bar


#4楼

“在Java中,我们被教导有关公共/私有/保护变量”

“为什么在python中不需要?”

出于同样的原因,在Java中不需要

您可以自由使用-或不使用privateprotected

作为Python和Java程序员,我发现privateprotected是非常重要的设计概念。 但是实际上,在成千上万的Java和Python行中,我从未真正使用过privateprotected

为什么不?

这是我的问题“不受谁保护?”

我团队中的其他程序员? 他们有出处。 受保护的人何时可以更改它意味着什么?

其他团队的其他程序员? 他们在同一家公司工作。 他们可以-通过电话-获取消息来源。

客户? (通常)是按需租用的程序。 客户(通常)拥有代码。

那么,到底是谁在保护我?


#5楼

下划线约定中存在私有变量的变体。

In [5]: class Test(object):
   ...:     def __private_method(self):
   ...:         return "Boo"
   ...:     def public_method(self):
   ...:         return self.__private_method()
   ...:     

In [6]: x = Test()

In [7]: x.public_method()
Out[7]: 'Boo'

In [8]: x.__private_method()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-8-fa17ce05d8bc> in <module>()
----> 1 x.__private_method()

AttributeError: 'Test' object has no attribute '__private_method'

有一些细微的差异,但是出于编程模式思想纯净的考虑,其足够好。

@private装饰器中有一些示例可以更紧密地实现该概念,但是可以使用YMMV。 可以说也可以编写一个使用meta的类定义

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!