2017-10-20 103 views
3

我想了解类继承如何在Python 3中工作,特别是私人领域如何与本地和继承方法进行交互。这里有一些例子来说明这个问题。Python3:类继承和私有字段

首先,如果在超类的变量var是公共的,然后在子类中的任何方法也可以改变它:

class Superclass: 
    var = 1 
    def getVar(self): 
     print(self.var) 

class Subclass(Superclass): 
    def __init__(self): 
     self.var = 123 

my_object = Subclass() 
my_object.getVar() # outputs 123 

同样是不正确的,如果在超类中的变量__var是私人,任何继承的方法将忽略由子类进行修改:

class Superclass: 
    __var = 1 
    def getVar(self): 
     print(self.__var) 

class Subclass(Superclass): 
    def __init__(self): 
     self.__var = 123 

my_object = Subclass() 
my_object.getVar() # outputs 1! 

子类中的本地方法可以修改它:

class Superclass: 
    __var = 1 

class Subclass(Superclass): 
    def __init__(self): 
     self.__var = 123 
    def getVar(self): 
     print(self.__var) 

my_object = Subclass() 
my_object.getVar() # outputs 123 

但为了使用继承的方法改变了其价值,我必须在子类中使用self._Superclass__var代替self.__var

class Superclass: 
    __var = 1 
    def getVar(self): 
     print(self.__var) 

class Subclass(Superclass): 
    def __init__(self): 
     self._Superclass__var = 123 

my_object = Subclass() 
my_object.getVar() # outputs 123 

为什么会出现这种情况?是否私有字段不被子类继承,因此Subclass中的变量self.__var不指向与Superclass中的变量self.__var相同的值?

+6

Python中没有专用字段。如果用'__'前缀属性名称,则会调用名称修改,其中自动插入“拥有”类的名称,以防止在子类中冲突属性名称。它并不妨碍你访问它,它只是要求你包含拥有类的名字。请参阅https://docs.python.org/3/tutorial/classes.html#private-variables – kindall

+4

Python中有*没有专用字段*。这是你根本的误解。您正在使用双下划线名称mangling,它可以防止继承类中的名称冲突,而不是阻止访问。另外,我希望你意识到你正在定义*类级变量*,相当于其他语言中的“静态变量”,而不是实例变量。 –

+1

我认为值得加上这个澄清作为一个答案,因为这是一个很好的问题与不同背景的人来。 –

回答

3

Python并不真的有私有变量,有两个约定:用下划线(_var)前缀

  • 变量用来让你和其他人都知道,它的意图是私人
  • 变量有两个undersores(__var)也被Python解释器错位以及通过类名称的前缀为前缀,但他们还是喜欢self._Superclass__var访问你的榜样

另见documentation

你的代码还有一个问题 - 你正在使用类变量,而不是实例变量(这通常称为其他语言中的静态类变量)。

检查这个例子:

class Superclass: 
    var = 1 

    def getVar(self): 
     print(self.var) 

my_object = Superclass() 
my_object2 = Superclass() 
my_object.getVar() # outputs 1 
my_object2.getVar() # outputs 1 

Superclass.var = 321 # this value is share across all instances 
my_object.getVar() # outputs 321 
my_object2.getVar() # outputs 321 

而且当你正在做你的方法self.var = xxx任务,你只是隐藏类级变量,并用相同的名字添加新的实例级变量。

另请参阅文档:https://docs.python.org/3.6/tutorial/classes.html#class-and-instance-variables

+0

由于这些评论的作者没有写出我可以选择的答案,您是否希望将这些信息添加到上面的答案中,以便我可以选择它?因为现在,和你的回答一样有用,它并不完全解决我提出的问题。 –

+1

@ gilberto.agostinho.f好的,我更新了答案。 –