2016-11-17 135 views
0

我最近开始学习python,并且我很难在python中如何继承。python中的继承,属性错误

我创建了两个类,一个名为Animal,另一个名为Dog。 Dog类继承Animal类。我在动物类中有一些属性,如名称,高度,声音等,我想在Dog类中使用。我使用init动物类的方法设置属性。

class Animal: 
    __name = "" 
    __height = 0 
    __weight = 0 
    __sound = 0 

    def __init__(self, name, height, weight, sound): 
     self.__name = name 
     self.__height = height 
     self.__wight = weight 
     self.__sound = sound 

    def set_name(self, name): 
     self.__name = name 

    def get_name(self): 
     return self.__name 

    def set_height(self, height): 
     self.__height = height 

    def get_height(self): 
     return self.__height 

    def set_weight(self, weight): 
     self.__weight = weight 

    def get_weight(self): 
     return self.__weight 

    def set_sound(self, sound): 
     self.__sound = sound 

    def get_sound(self): 
     return self.__sound 

    def get_type(self): 
     print("Animal") 

    def tostring(self): 
     return "{} is {} cm tall and {} kilograms and says {}".format(self.__name, 
                     self.__height, 
                     self.__weight, 
                     self.__sound) 


cat = Animal("whiskers", 50, 20, "meow") 
print(cat.tostring()) 


class Dog(Animal): 
    __owner = None 

    def __init__(self, name, height, weight, sound, owner): 
     super(Dog, self).__init__(name, height, weight, sound) 
     self.__owner = owner 

    def set_owner(self, owner): 
     self.__owner = owner 

    def get_owner(self): 
     return self.__owner 

    def get_type(self): 
     print("dog") 

    def tostring(self): 
     return '{} is {} cm tall and {} kilograms and says {} His owner is {}'.format(self.__name, 
                         self.__height, 
                         self.__weight, 
                         self.__sound, 
                         self.__owner) 

    def multiple_sounds(self, how_many=None): 
     if how_many is None: 
      print(self.get_sound()) 
     else: 
      print(self.get_sound() * how_many) 
my_dog = Dog("spot", 50, 40, "Ruff", "Derek") 
print(my_dog.tostring()) 

问题是当我尝试打印使用Dog类的对象的所有属性,会显示一个错误,说“

*line 73, in tostring 
    return '{} is {} cm tall and {} kilograms and says {} His owner is {}'.format(self.__name, 
AttributeError: 'Dog' object has no attribute '_Dog__name'* 

谁能帮我看看这个问题在这个代码?

回答

2

以双下划线开头的成员是私有类型,所以它们不能从cild类访问,你应该使用单下划线Python不使用像C++或java这样的隐式访问说明符,而是使用特殊的名称约定:名称为_前缀用于保护,__的名称为私有。此外python不检查你是否违反了这个约定,在类之外访问受保护的或私有的方法被认为是一种不好的做法。如果你用双下划线开始一个名字,它会以一种特殊的方式被破坏。所以__name实际上变成了_Animal__name当你在Animal类和_Dog__name当你在Dog中使用它。

+0

问题通过将双下划线更改为单下划线解决。谢谢您的帮助 ! – Yousaf

1

问题是你的名字中有双下划线前缀。他们触发了名称混乱。

你应该避免使用这些。他们没有做你期望的。

1

在Python中使用双下划线使变量“私有”。它类似于在其他语言中使用private关键字。如果要访问父类之外的属性,则需要删除它们。

Python documentation touches on this subject

由于存在一个有效的用例为类私有成员(即,以避免名称的名称冲突与由子类定义名称),存在对这样的机制支持有限,所谓的名字mangling。 __spam(至少包含两个前导下划线,最多一个尾部下划线)的任何标识符都被_classname__spam文本替换,其中classname是当前类名,前导下划线已被删除。只要它在类的定义内发生,就不会考虑标识符的语法位置。 (强调我的)