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

2024-04-25 12:53:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我来自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())

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

例如:

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

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

为什么Python中不需要这样做


Tags: theselfdefshow世界模式msgjava
3条回答

正如上面许多评论所正确提到的,让我们不要忘记访问修饰符的主要目标:帮助代码用户理解什么应该更改,什么不应该更改。当你看到一个私人领域时,你不会乱来。因此,它主要是语法上的糖分,在Python中,通过u和uu可以很容易地实现

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

如果出于某种原因希望模拟私有变量,则始终可以使用来自PEP 8__前缀。Python会对变量名进行修改,比如__foo,这样它们就不容易被包含它们的类之外的代码看到(尽管如果你有足够的决心,你可以绕过它,就像你可以绕过Java的保护一样)

按照同样的惯例,_前缀意味着远离,即使在技术上没有阻止你这样做。您不能随意使用另一个类的变量,这些变量看起来像__foo_bar

python中的私有变量或多或少是一种攻击:解释器故意重命名变量

class A:
    def __init__(self):
        self.__var = 123
    def printVar(self):
        print self.__var

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

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

>>> x.printVar() # this gives back 123

但你可以很容易地做到:

>>> 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

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

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

相关问题 更多 >