我来自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中不需要这个?


当前回答

如前所述,可以通过在变量或方法前面加上下划线来表示它是私有的。如果您觉得这还不够,还可以使用属性装饰器。这里有一个例子:

class Foo:

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

    @property
    def bar(self):
        """Getter for '_bar'."""
        return self._bar

This way, someone or something that references bar is actually referencing the return value of the bar function rather than the variable itself, and therefore it can be accessed but not changed. However, if someone really wanted to, they could simply use _bar and assign a new value to it. There is no surefire way to prevent someone from accessing variables and methods that you wish to hide, as has been said repeatedly. However, using property is the clearest message you can send that a variable is not to be edited. property can also be used for more complex getter/setter/deleter access paths, as explained here: https://docs.python.org/3/library/functions.html#property

其他回答

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

更多信息请参见这里。

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

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

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

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

如前所述,可以通过在变量或方法前面加上下划线来表示它是私有的。如果您觉得这还不够,还可以使用属性装饰器。这里有一个例子:

class Foo:

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

    @property
    def bar(self):
        """Getter for '_bar'."""
        return self._bar

This way, someone or something that references bar is actually referencing the return value of the bar function rather than the variable itself, and therefore it can be accessed but not changed. However, if someone really wanted to, they could simply use _bar and assign a new value to it. There is no surefire way to prevent someone from accessing variables and methods that you wish to hide, as has been said repeatedly. However, using property is the clearest message you can send that a variable is not to be edited. property can also be used for more complex getter/setter/deleter access paths, as explained here: https://docs.python.org/3/library/functions.html#property

“在java中,我们学习了公共/私有/受保护变量”

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

出于同样的原因,它在Java中不是必需的。

您可以自由使用或不使用private和protected。

作为Python和Java程序员,我发现私有和受保护是非常非常重要的设计概念。但实际上,在数万行Java和Python代码中,我从未真正使用过private或protected。

为什么不呢?

我的问题是"被谁保护?"

我团队中的其他程序员?他们有消息来源。当他们可以改变的时候,保护意味着什么?

其他团队的其他程序员?他们在同一家公司工作。只要打个电话,他们就能找到线人。

客户吗?这是一种雇佣式编程(通常)。客户机(通常)拥有代码。

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

在Python 3中,如果你只是想“封装”类属性,就像在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())

要实例化此操作:

ss = Simple("lol")
ss.show()

注意:print(ss.__s)将抛出一个错误。

实际上,Python 3会混淆全局属性名。就像在Java中一样,它将此转换为“私有”属性。属性名仍然是全局的,但是以一种不可访问的方式,就像其他语言中的私有属性一样。

但是不要害怕。没关系。它也起作用了。;)