Python在类中有"私有"变量吗?

Omn*_*ent 532 python private class

我来自Java世界并阅读Bruce Eckels的Python 3模式,食谱和成语.

在阅读类时,接着说在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())
Run Code Online (Sandbox Code Playgroud)

如果这是真的,那么类的任何对象都Simple可以只改变s类外的变量值.

例如:

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

在Java中,我们学习了有关公共/私有/受保护变量的知识.这些关键字是有意义的,因为有时你想要类中的变量,类外没有人可以访问.

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

Kir*_*ser 915

这是文化.在Python中,您不会写入其他类的实例或类变量.在Java中,如果你真的想要,没有什么能阻止你做同样的事情- 毕竟,你总是可以编辑类本身的源来达到同样的效果.Python放弃了安全性的假装并鼓励程序员负责.在实践中,这非常好用.

如果由于某种原因想要模拟私有变量,可以始终使用PEP 8中__前缀.Python破坏了变量的名称,使得它们不容易被包含它们的类外的代码看到(尽管如果你足够坚定,你可以解决它,就像你可以绕过Java的保护,如果你在它工作).__foo

按照相同的惯例,即使您没有在技术上阻止这样做,_前缀意味着远离.你不会玩另一个看起来像__foo或类的变量_bar.

  • 我倾向于选择python方式,但我认为java方式并不像你所说的那样毫无意义.快速声明私有内容会告诉某人阅读代码非常有用的内容:此字段仅在此类中进行修改. (153认同)
  • @Omnipresent,你可以使用反射. (63认同)
  • 让我直截了当,因此Python不实现公共属性或私有属性,因为"它是安全的借口并鼓励程序员负责",但是社区鼓励使用"_"来表示私有变量和方法?也许python应该定义公共和私有没有?它们的主要目的是告诉您应该使用什么API来与类进行交互.它们作为文档告诉您使用这些方法而不使用它们.它们不是"安全的借口",它们是API文档,甚至可以由IDE用来指导您! (62认同)
  • 这是一个很好的答案,你的推理肯定是有效的,但我不同意一个方面.访问修饰符的目的从来就不是**安全**.相反,它们是明确划分(并在很大程度上强制执行)类的哪些部分被视为内部以及哪些部分暴露给该类的外部用户的手段.约定(文化)肯定是访问修饰符的有效替代方法,并且这两种方法都有其优点和缺点,但是目的是语言级访问修饰符以任何方式在通常的意义上"安全",这是误导的.字. (14认同)
  • 那讲得通.但是,我不认为java中有任何方法可以访问类外的私有变量(除了实际更改类的源之外).在那儿? (12认同)
  • @David - 推测是我们都是成年人.不要破坏你无法修复的东西!在这种情况下,这意味着你不应该乱用像__foo或_bar这样的私有成员.再一次,在实践中,没有一个非常好的理由就没有做到这一点.它可能在理论上并不纯粹,但我从来没有见过真实世界的情况,这是一个问题. (7认同)
  • 可能太晚了,但是当java代码在带有配置的SecurityManager的jvm中运行时,java中的访问修饰符会产生_very real_ security影响.配置SecurityManager时运行的代码_cannot_规避访问修饰符限制. (7认同)
  • 拉里·沃尔很好地表达了**文化理念**(对于Perl,在perlmod 5.0手册页上):_"Perl并没有对强制隐私的迷恋.它更希望你不在客厅,因为你不是'邀请,不是因为它有霰弹枪."_同样的想法为Python. (7认同)
  • 有**公共**,**私有**和**受保护**来强制访问,而不是Python的*_voluntary_*下划线*__约定__*.[与Python不同,在Ruby中](https://www.ruby-lang.org/en/documentation/ruby-from-other-languages/to-ruby-from-python/).[PHP中的可见性](http://php.net/manual/en/language.oop5.visibility.php)在许多**解释的**语言中,如_Ruby _,_PHP_,有一个可见性概念但不在_Python_中, _Python_他们有*文化* (6认同)
  • 似乎没有具体提到的东西是可见性使调试更容易:如果你有问题,并且该方法或变量超出某些代码的范围,你知道代码没有调用那个函数将错误值应用于某个变量或直接但错误地修改变量.使用Python中的"__",您无法保证它,但它变得不太可能.在其他语言(Java,C++)中,它肯定是有用的(即使它会让想要添加/修改功能的开发人员感到惊愕). (5认同)
  • 值得注意的是,作为一种或多或少的解释语言,C++编译器(我认为Java编译器)可能具有的许多考虑因素,在python中根本不存在.私有属性或方法可以具有各种优化以加速来自本地对象的访问.它说"嘿编译器,我只会从这个对象访问,所以不要担心所有的文件工作让我从外面看到,如果那会帮助你,你甚至可以内联我".在蟒蛇的情况下,它有点莫名其妙. (4认同)
  • 在Python中__foo也是如此,而_bar意味着你可以,但可能不应该. (3认同)
  • 重要的是,您编写的代码可以整齐有效地解决您的问题.任何想要破解你的代码的人最终都会这样做.但他们可能应该花时间正确编码:-) (3认同)
  • @dVaffection如果Iain M Banks教会了我什么,那就是文化永远胜利. (3认同)
  • 反思并不是你可以"偶然"做的事情,而且据我所知,这是弄乱私有变量的唯一方法.令人惊讶的是,同时Python鼓励我们成为"负责任"的程序员,同时谈论新手甚至可以在python中编码! (3认同)
  • @AneeshBarthakur 您也不能“意外”访问`AnotherClass.__foo`,因为您必须计算其特定于实现的派生名称。在 CPython 3.5 中,它看起来像 `AnotherClass._AnotherClass__foo`。当然,这是可以克服的(只要你知道你的代码将在什么实现上运行!)但这是一个巨大的警告信号,你不应该这样做。 (3认同)
  • 有趣的是,我来自PHP背景,我想知道它在实践中是如何工作的.如果使用的语言不是Python,那么类能够修改私有成员是不是很危险? (2认同)
  • 不是我所知道的,但关键是你可以*编辑源代码,甚至编译字节码.如果你有足够的决心搞乱那个阶级的内脏,那么没有什么可以阻止你.那么为什么要花费精力来防止它,而不是依靠惯例和薄机制来说"不要那样做!" 当它归结为它时,无论它通常是多么糟糕的想法,有时你真的*做*想要摆弄你不应该的地方. (2认同)
  • +1:我们都是成年人."私有"和"受保护"关键字是有趣的注释,但变量名称上的前导`_`也是如此.Python作为源分发 - 并运行 - .没有".class"文件来隐藏实现背后的内容. (2认同)
  • Python确实具有公共变量,半公共变量和私有变量:`foo`,`_foo`和`__foo`。IDE和其他工具支持它们,并调用对类内部的外部引用。但同样,它并没有强制执行:如果您决心逃离沙盒,那就继续吧,但是不打碎东西的责任就在您身上。 (2认同)
  • @Omnipresent:是的,你可以.Java具有反射API:http://tutorials.jenkov.com/java-reflection/private-fields-and-methods.html"私有"在访问级别方面一直是一个误导性术语.它更像是"隐藏在引擎盖下".任何人都可以打开引擎盖,但大多数人不应该. (2认同)
  • Python是OOP,而不是Python的方式,所以它不是一般的"oop方式". (2认同)
  • 我们花了数年时间指望程序员要小心,不要碰他们不该碰的东西。你猜怎么着,事故发生了。这就是为什么公共/私有/受保护被添加到许多语言中的原因。就像汽车警报器(或“俱乐部”)一样,它们会阻止整类小偷,但不会阻止铁杆小偷。没有什么会阻止他们。public/private 的目的是获得最大的收益,消除偶然发生的常见错误。 (2认同)
  • @Evvo 你不会“意外地”输入前导下划线 - 所以每当你输入类似 `someobj._attrib` 的东西时,你**知道**你正在破坏封装。从这一刻起,您对可能发生的任何不良后果承担全部责任。 (2认同)
  • @Bruno——各种各样的事情都是偶然发生的,有匆忙的人,有的人只是想走捷径去处理其他事情,但无意中认为你在不同的窗口中输入。这就是可见性控制的目的,以避免此类事故或误解。尤其是在处理第三方软件时。我作为一名开发人员已经有很长一段时间了,见过你能想象到的各种“哎呀”。当谈到纪律和严格性时,我对编译器的信任远胜于对人类的信任。 (2认同)
  • @Evvo我已经作为专业程序员工作了20多年了,我自己已经看过很多哎呀,我肯定不信任编译器 - 我宁愿相信一个好的linter和一个良好的unitttest覆盖.没有办法制作一种愚蠢的语言--Java和Ada都失败了(对Ada来说是一种非常史诗般的方式) - 所以我们不要自欺欺人地认为如果编译它是正确的. (2认同)
  • @LeonardoRaele 我认为你不太明白这一点。我十多年前所写的内容是,Python 并不将此类事物视为防弹合约。它在输入方面采用了相同的方法:尽管您可以说函数对整数进行操作,但如果您确实想滥用系统,则可以传入字符串。因此,Python 方法不是硬性规定,而是记录您应该如何使用系统,但如果您确实必须这样做,则不会极力阻止您做相反的事情。 (2认同)

wat*_*HUN 141

python中的私有变量或多或少是一个hack:解释器故意重命名变量.

class A:
    def __init__(self):
        self.__var = 123
    def printVar(self):
        print self.__var
Run Code Online (Sandbox Code Playgroud)

现在,如果您尝试__var在类定义之外访问,它将失败:

 >>>x = A()
 >>>x.__var # this will return error: "A has no attribute __var"

 >>>x.printVar() # this gives back 123
Run Code Online (Sandbox Code Playgroud)

但你可以很容易地逃脱这个:

 >>>x.__dict__ # this will show everything that is contained in object x
               # which in this case is something like {'_A__var' : 123}

 >>>x._A__var = 456 # you now know the masked name of private variables
 >>>x.printVar() # this gives back 456
Run Code Online (Sandbox Code Playgroud)

您可能知道OOP中的方法是这样调用的:x.printVar() => A.printVar(x)如果A.printVar()可以访问某个字段x,则此字段也可以在外部 访问A.printVar()...毕竟,函数是为了可重用性而创建的,内部语句没有特殊的功能.

当涉及编译器时,游戏是不同的(隐私是编译器级概念).它知道带有访问控制修饰符的类定义,因此如果在编译时没有遵循规则,它就会出错

  • 简而言之,这不是封装 (2认同)
  • 我想知道PHP是否与其愚蠢的私有变量有类似的东西 - 因为私有变量在解释语言中并没有真正意义 - 我的意思是,如果知道x变量是私有的,它是否可以进行优化,如果它没有被编译? (2认同)
  • @watashiSHUN“总之,这不是封装” =>是的。封装仅使用公共API,因此可以保护客户端代码免受实现更改的影响。命名约定是分辨API是什么以及实现是什么的一种非常有效的方法,关键是它可以正常工作。 (2认同)
  • 封装与是否可以通过复杂的方法访问私有变量无关。任何人都可以在 C++ 中直接访问具有“私有变量”的内存。Python还可以访问“私有变量”。有什么大不了的。 (2认同)

小智 27

正如上面许多评论中正确提到的那样,让我们​​不要忘记访问修饰符的主要目标:帮助代码用户理解应该更改的内容和不应该更改的内容.当你看到私人领域时,你不会乱用它.所以它主要是语法糖,可以通过_和__在Python中轻松实现.

  • 我认为这和任何一点一样重要.调试代码时(我知道,我是介绍bug的弱点),知道哪些类可以更改成员变量,简化了调试过程.至少,如果变量受某个范围的保护.类似的概念是C++中的const函数.我*知道*那里的成员变量没有改变,所以我甚至不把这个方法看作是一个糟糕的变量设置的潜在原因.虽然它可以进行类扩展/添加功能的后续开发,但限制代码的可见性使其更容易调试. (3认同)

S.L*_*ott 19

"在java中,我们已经了解了公共/私有/受保护的变量"

"为什么在python中不需要?"

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

你可以自由使用 - 或者不使用privateprotected.

作为一个Python和Java程序员,我发现,privateprotected是非常,非常重要的设计理念.但实际上,在数以万计的Java和Python系列中,我从未真正使用过private或者protected.

为什么不?

这是我的问题"受到谁保护?"

我团队中的其他程序员?他们有源头.受保护意味着何时可以改变它?

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

客户端?这是一种招聘工作(一般).客户(通常)拥有代码.

那么,究竟是谁 - 我保护它免受伤害?

对.拒绝阅读API评论的精神分裂症反社会人士阻止.

  • -1:我同意Porculus.它不是关于禁止访问或隐藏某些东西,而是关于*隐式*API文档.开发人员以及编译器/解释器/代码检查器可以轻松查看建议使用哪些成员以及哪些成员不应被触及(或至少小心).在大多数情况下,如果一个班级或模块的所有成员都是公开的,那将是一个可怕的混乱.考虑私人/受保护/公共成员作为服务的区别,说:"嘿,这些成员很重要,而这些成员在内部使用,可能对你没用." (108认同)
  • @ S.Lott我不是一个蟒蛇人,所以我不会从这个角度发表评论.然而,作为一名java开发人员,这真是令人恐惧的建议.-1 (33认同)
  • 在讨论的后期,但是Porculus和Oben在这里请求的所有内容都通过"使用下划线加上前缀"约定来完全处理(并且没有编译器强制执行该约定会造成的损害) (21认同)
  • 哇.你完全忽略了这一点,你提出了一个非常糟糕的建议,你侮辱了在这一点上不同意你的人,但你仍然得到了这个"答案"的徽章和1000多个声望点. (9认同)
  • @ S.Lott:我同意API文档具有更高的优先级,并且通常是传达API的预期用途的唯一方式.但有时成员姓名和知名度(就私人/公共而言)充分说明了问题.此外,我认为隐含文档的概念在没有API检查的编辑器中效果不佳,但在代码完成的IDE中它确实很有用.假设您已经在前一段时间阅读过API文档,它可以帮助您记住如何使用类.如果私人和公共成员之间没有区别,事情就不会那么聪明. (7认同)
  • @ncoghlan这些观点遍布互联网和Python出版物.不会使他们成为经文.许多人认为编译器强制执行接口,强大的数据封装和打字是非常有益的."隐私无助于设计封装." 同意不同意."私人只是......帮助那些无法阅读文档或拒绝遵循文档的人." 再次,愚蠢.我们都同意,高级,松散类型语言和低级强类型语言都有好处.它们都是工具箱中的工具! (7认同)
  • @hiwaylon:绝对正确.完全同意.封装是一种设计特征.隐私无助于将设计封装起来.它只提供编译器支持,以防止人们使用他们不应该使用的属性.对接口进行编程就是拥有一个已定义的接口并记录它.Private只是编译器支持,以帮助那些无法阅读文档或拒绝遵循它的人. (5认同)
  • @hiwaylon:如果你坚持将封装 - 一种设计技术 - 与隐私 - 实施技术混为一谈 - 我就会明白为什么你声称隐私是神奇必不可少的.考虑一个不使用`private`的C++程序员.你是说一个封装好,设计好的设计神奇地无法显示出良好的封装,因为没有使用`private`?如果是这样,那么选择性地删除隐私的`friend`声明将使设计神奇地"未封装".即使控制得很好?我不买`private` ==很好. (4认同)
  • 直接访问公共数据违反了封装.虽然下划线约定有助于传达意图,但语言中"private"关键字的存在肯定不是坏事. (4认同)
  • @Porculus:"让你的IDE很容易知道"......什么?我的IDE是一个编辑器.我是设计师.我知道设计是什么.我的IDE是一个编辑器,什么都不知道.谁是"意外使用其他任何东西"的神秘"无人"?特别?那个人是谁?他们为什么不知道使用API​​的正确方法? (3认同)
  • @hiwaylon这是一个"同意成人"的API设计方法 - 领先的下划线说"如果你开始搞乱这个问题,你就是自己的,但如果你认为这是必要的,语言不会阻止你".另一方面,执法使最初的API设计者处于这样的位置:"你不能以我未预先计划的方式使用我的API.即使你愿意承担相关的风险,编译器也只是赢了不要让你." (3认同)
  • @ S.Lott - 虽然我半同意,但是在Java中省略了`public` /`private`并不**意味着"无论如何".它为成员提供默认可见性,这意味着它在其包中可见,但*不在其他任何地方(包括子包).在大多数情况下,您*必须使用功能可见性. (3认同)
  • 我曾经认为私人公众有点傻,但是在正确使用类之后,你可能在类上有大量非常小的函数,你希望能够添加仅指定用于的类的方法.该类中的其他方法.关键是,如果你知道只有同一个类的不同方法调用该方法才有意义,那么将其设为私有,如果你在外面,你就不会考虑它. (3认同)
  • 可能会保护我的骨头错误吗?我同意访问修饰符可以帮助您推断代码的概念.它们提供了编写库的人所期望的编译时间通知(假设他们知道他们在做什么).我喜欢Python,但是说你在整个职业生涯中从未使用过"私人"或"受保护",这似乎过于顽固.在没有Python等文化惯例的情况下,将您的意图传达给编译器是有价值的.在大多数支持它们的语言中,其他语言希望您利用它们来表达您的意图. (3认同)
  • 同意S.Lott.如果整点是隐含的使用指示,Python用下划线前缀解决它,并且因为没有其他点,正如我们已经得出的结论,Java的私有/公共是一种不必要的复杂性. (3认同)
  • @ncoghlan 编译器强制执行会造成什么危害? (2认同)
  • @hiwaylon Encapsulation 按照惯例意味着如果有充分的理由(例如注入额外的日志记录以查找应用程序状态错误更新的来源),您可以破坏封装。使用编译器级别的强制执行,您根本无法做很多在处理维护和测试现实世界软件时非常有用的事情(看看 Java 和 C++ 的设计模式:其中许多是关于编写大量额外代码以提供你一些额外的扩展点)。 (2认同)
  • 执法不是全部吗?在Java中,编译器强制执行编写者的意图.在Python中,缺少一个工作程序表明Python解释器强制执行写操作的意图.OTOH,在运行时使用Java类错误地指示一个人没有阅读文档或理解设计.在Python中它表示相同.这取决于你想让其他编码器使用什么,以及你希望他们如何发现如何使用它.所有人都会使用文档.Java会让你在编译时(或之后)读取.程序爆炸时的Python. (2认同)
  • 私有和受保护变量强制执行良好的设计实践.我们都是人类,有时我们都会感到懒惰或疲惫.许多人不能强迫自己戒烟或开始锻炼,即使他们知道什么对他们最有利.同样,如果没有这样的障碍,很多人都会想要使用私有变量.宣布一些私密的东西正在做出你将要实现的承诺.优点是您几乎可以完美地封装一段代码,对其进行润色并对其感到安全.这种安全性在python中永远不会发生. (2认同)

Sha*_*yne 18

下划线约定中有一些私有变量.

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'
Run Code Online (Sandbox Code Playgroud)

有一些微妙的差异,但为了编程模式的思想纯度,它足够好.

有一些@private装饰器的例子更接近实现这个概念,但是YMMV.可以说,人们也可以写一个使用meta的类定义

  • 我意识到派对已经很晚了,但谷歌搜索问题时会出现这个链接.这并不能说明整个故事.`__x`作为类`A`中的变量实际上是由编译器重写为`_A__x`,它仍然不是完全私有的,仍然可以被访问. (14认同)
  • 当然,如果我看到一个名为“_A__x”的变量,我不会碰它。它可能具有传染性。我会逃离它。 (2认同)
  • 当然,这不是*真正的*私人。但是,在 C++ 和 Java(等)中强制执行私有的原理(编译器优化)在 Python 中并不存在,所以按照约定私有就足够了。Python 的惯例通常是它相信你会在没有监督的情况下表现自己。(这是一个新手陷阱,但你知道,只要考虑一下班级设计和消费即可) (2认同)

Hat*_*ter 12

Python 没有像 C++ 或 Java 那样的任何私有变量。如果需要,您也可以随时访问任何成员变量。但是,在 Python 中不需要私有变量,因为在 Python 中公开类成员变量也不错。如果您需要封装成员变量,您可以稍后使用“@property”来完成此操作,而不会破坏现有的客户端代码。

在 python 中,单个下划线“_”用于表示方法或变量不被视为类的公共 api 的一部分,并且 api 的这一部分可能会在不同版本之间发生变化。您可以使用这些方法/变量,但如果您使用此类的较新版本,您的代码可能会中断。

双下划线“__”并不意味着“私有变量”。您可以使用它来定义“类本地”变量,并且不能轻易被子类覆盖。它破坏了变量名称。

例如:

class A(object):
    def __init__(self):
        self.__foobar = None # will be automatically mangled to self._A__foobar

class B(A):
    def __init__(self):
        self.__foobar = 1 # will be automatically mangled to self._B__foobar
Run Code Online (Sandbox Code Playgroud)

self.__foobar 的名称在 A 类中被自动修改为 self._A__foobar。在 B 类中它被修改为 self._B__foobar。所以每个子类都可以定义自己的变量 __foobar 而不覆盖其父变量。但是没有什么可以阻止您访问以双下划线开头的变量。但是,名称修改可防止您偶然调用此变量/方法。

我强烈建议您在 Pycon 2013 中观看 Raymond Hettinger 的Python 类开发工具包,它提供了一个很好的示例,为什么以及如何使用 @property 和“__”-instance 变量。

如果你已经暴露了公共变量并且需要封装它们,那么你可以使用@property。因此,您可以从最简单的解决方案开始。除非您有具体的理由不这样做,否则您可以将成员变量设为公开。下面是一个例子:

class Distance:
    def __init__(self, meter):
        self.meter = meter


d = Distance(1.0)
print(d.meter)
# prints 1.0

class Distance:
    def __init__(self, meter):
        # Customer request: Distances must be stored in millimeters.
        # Public available internals must be changed.
        # This would break client code in C++.
        # This is why you never expose public variables in C++ or Java.
        # However, this is python.
        self.millimeter = meter * 1000

    # In python we have @property to the rescue.
    @property
    def meter(self):
        return self.millimeter *0.001

    @meter.setter
    def meter(self, value):
        self.millimeter = meter * 1000

d = Distance(1.0)
print(d.meter)
# prints 1.0
Run Code Online (Sandbox Code Playgroud)


Dan*_*son 10

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

有关详情,请参阅此处.

通常,与其他语言相比,Python的面向对象实现有点原始.但实际上,我喜欢这个.这是一个概念上非常简单的实现,非常适合语言的动态风格.


Isa*_*old 10

如前所述,您可以通过在其前面添加下划线来指示变量或方法是私有的.如果您觉得这不够,您可以随时使用property装饰器.这是一个例子:

class Foo:

    def __init__(self, bar):
        self._bar = bar

    @property
    def bar(self):
        """Getter for '_bar'."""
        return self._bar
Run Code Online (Sandbox Code Playgroud)

这样,引用的某个人或某个东西bar实际上是引用bar函数的返回值而不是变量本身,因此可以访问但不能更改它.但是,如果有人真的想要,他们可以简单地使用_bar并为其分配新值.正如已经反复说过的那样,没有万无一知的方法来阻止某人访问你想要隐藏的变量和方法.但是,使用property是您可以发送的最清晰的消息,即不编辑变量.property也可以用于更复杂的getter/setter/deleter访问路径,如下所述:https://docs.python.org/3/library/functions.html#property


小智 8

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

如前所述,这再次涉及文化.我一直致力于读取和编写其他类变量的项目是免费的.当一个实现被弃用时,需要花费更长的时间来识别使用该功能的所有代码路径.当强制使用setter和getter时,可以很容易地编写一个debug语句来识别已经调用过的方法以及调用它的代码路径.

当您在一个任何人都可以编写扩展的项目中,通知用户有关在几个版本中消失的弃用方法因此对于在升级时将模块破坏保持在最低限度至关重要.

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


小智 7

私人和受保护的概念非常重要.但是python - 只是一个用于原型设计和快速开发的工具,可用于开发的资源有限,这就是为什么python中的一些保护级别不是那么严格的原因.您可以在类成员中使用"__",它可以正常工作,但看起来不够好 - 每次访问此类字段都包含这些字符.

此外,你可以注意到python OOP概念并不完美,smaltalk或ruby更接近纯OOP概念.甚至C#或Java也更接近.

Python是非常好的工具.但它是简化的OOP语言.在语法和概念上简化.python存在的主要目标是为开发人员提供以非常快的方式编写具有高抽象级别的易读代码的可能性.

  • Private 和 Protected 的重要原因在于,在静态编译语言中,编译器可以创建对私有方法的直接调用,但必须依赖于公共方法的查找表。对于动态语言来说,这根本不是问题。最后,像 C++ 这样的语言对继承和方法解析也有影响。Python 和 Ruby 的 OO 实现非常相似,因此比较没有意义。Smalltalk 实际上没有公共/私人消息的概念。您可以自由地将私人添加为类别,但这纯粹是建议性的。 (3认同)

Fer*_*ezi 6

抱歉,“恢复”线程,但是,我希望这会对某人有所帮助:

在Python3中,如果您只想“封装”类属性(例如在Java中),则可以执行以下操作:

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

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

    def showMsg(self, msg):
        print(msg + ':', self.show())
Run Code Online (Sandbox Code Playgroud)

要实例化此操作,请执行以下操作:

ss = Simple("lol")
ss.show()
Run Code Online (Sandbox Code Playgroud)

注意:print(ss.__s)会抛出错误。

实际上,Python3将混淆全局属性名称。像在Java中一样,将其变为“私有”属性。该属性的名称仍然是全局的,但是以一种无法访问的方式,就像其他语言中的私有属性一样。

但是不要害怕。没关系 它也做这项工作。;)

  • 这自 Python 1.5.2 IIRC 以来就存在,并且它仍然不会阻止通过其损坏的名称访问该属性。 (2认同)