我来自Java世界,正在阅读Bruce Eckels的《Python 3 Patterns, Recipes and idiom》。

在阅读有关类的内容时,会继续说在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中不需要这个?


当前回答

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

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 decorator的例子更紧密地实现了这个概念,但你的情况可能会有所不同。可以说,也可以编写使用meta的类定义。

其他回答

正如上面许多评论所正确提到的,让我们不要忘记Access Modifiers的主要目标:帮助代码的用户理解应该改变什么,不应该改变什么。当你看到一个私有的字段时,你不要乱摆弄它。所以它主要是语法糖,这在Python中很容易通过_和__实现。

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

更多信息请参见这里。

一般来说,与其他语言相比,Python的面向对象实现有点原始。但实际上我很享受这个过程。这是一个概念上非常简单的实现,非常适合该语言的动态风格。

我是Python的新手但我有c#和JavaScript的背景。就特性而言,Python感觉像是两者的混合体。JavaScript在这方面也有问题,解决方法是创建一个闭包。这可以通过返回不同的对象来防止访问您不想公开的数据。

def print_msg(msg):
    # This is the outer enclosing function

    def printer():
        # This is the nested function
        print(msg)

    return printer  # returns the nested function


# Now let's try calling this function.
# Output: Hello
another = print_msg("Hello")
another()

https://www.programiz.com/python-programming/closure

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#emulating_private_methods_with_closures

关于源代码(更改访问权限,从而绕过Java或c++等语言封装):

您并不总是拥有源代码,即使您拥有源代码,这些源代码也由一个只允许特定程序员访问源代码的系统管理(在专业上下文中)。通常,每个程序员都负责某些类,因此知道自己能做什么,不能做什么。源代码管理器还锁定正在修改的源代码,当然,还管理程序员的访问权限。

所以根据经验,我更相信软件而不是人。所以约定很好,但多重保护更好,比如访问管理(真正的私有变量)+源代码管理。

它的文化。在Python中,不写入其他类的实例或类变量。在Java中,如果你真的想这样做,没有什么可以阻止你这样做——毕竟,你总是可以编辑类本身的源代码来达到同样的效果。Python放弃了安全的伪装,并鼓励程序员负责任。在实践中,这工作得非常好。

如果您出于某种原因想要模拟私有变量,您总是可以使用PEP 8中的__前缀。Python会修改像__foo这样的变量名,这样它们就不容易被包含它们的命名空间之外的代码看到(尽管如果你足够坚定,你可以绕过它,就像你可以绕过Java的保护一样)。

根据同样的约定,_前缀意味着_variable应该只在类(或模块)内部使用,即使技术上不阻止从其他地方访问它。你不会摆弄其他类的变量,比如__foo或_bar。