在Python 3.5中使用super()时的属性错误

时间:2017-01-02 09:31:12

标签: python python-3.x inheritance

这是一段学习继承的Python代码。

class Animal():
    __name= None
    __sound = None

    def __init__(self, name , sound):
        self.__name= name
        self.__sound = sound 
    def ToString(self):
        print ("The {} has the sound  {}".format(self.__name ,
                                                self.__sound))


cat = Animal('Tiger' , 'roars')
cat.ToString()


class Panther(Animal):
    __owner = None

    def __init__(self , name ,sound ,owner):
        self.__owner = owner
        super(Panther ,self).__init__(name, sound)
    def ToString(self):
        print(self.__owner)
        print(self.__name) 

leopard = Panther('Leopard' , 'roars' , 'Senegal')
leopard.ToString()

但是当我尝试在Pycharm中运行它时,我收到以下错误:

  

/Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5   /Users/venkat/PycharmProjects/PythonOneVideo/main.py老虎有   声音咆哮Senegal Traceback(最近的呼叫最后一次):文件   “/Users/venkat/PycharmProjects/PythonOneVideo/main.py”,第41行,in          leopard.ToString()文件“/Users/venkat/PycharmProjects/PythonOneVideo/main.py”,第35行,in   的ToString       print(self .__ name)AttributeError:'Panther'对象没有属性'_Panther__name'

     

使用退出代码1完成处理

调用超类构造函数有什么问题? 为什么会出现此错误以及如何解决此问题? 任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:4)

几个问题:

  • py {3 super的语法:super().__init__(name, sound)
  • name mangling:以__开头的实例变量(两个下划线)将为它们添加_ClassName。子课程将无法以通常的方式访问它们。
  • ToString:为什么不__str__(不要在__str__内打印;只返回str)?
  • 什么是类变量(_name等)?为什么不把它们作为实例变量(self._name)?

这辆工程巴士不完整......

class Animal():
    # _name= None
    # _sound = None

    def __init__(self, name , sound):
        self._name= name
        self._sound = sound

#    def ToString(self):
#        print ("The {} has the sound  {}".format(self._name ,
#                                                self._sound))

    def __str__(self):
        fmt = 'The {self._name} has the sound {self._sound}'
        return fmt.format(self=self)

cat = Animal('Tiger' , 'roars')
print(cat)

class Panther(Animal):
    # _owner = None

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

#    def ToString(self):
#        # print(self._owner)
#        print(self._name)

leopard = Panther('Leopard' , 'roars' , 'Senegal')
print(leopard)

答案 1 :(得分:1)

从属性中删除两个前导下划线:

class Animal():
    name= None
    sound = None

    def __init__(self, name , sound):
        self.name= name
        self.sound = sound 
    def ToString(self):
        print ("The {} has the sound  {}".format(self.name ,
                                                self.sound))


cat = Animal('Tiger' , 'roars')
cat.ToString()


class Panther(Animal):
    owner = None

    def __init__(self , name ,sound ,owner):
        self.owner = owner
        super(Panther ,self).__init__(name, sound)
    def ToString(self):
        print(self.owner)
        print(self.name) 

leopard = Panther('Leopard' , 'roars' , 'Senegal')
leopard.ToString()

输出:

The Tiger has the sound  roars
Senegal
Leopard

两个主要下划线使您的属性"私有"。 这是我name mangling完成的,即在所有属性前面添加_ClassName和两个前导下划线。这可以防止你继续工作。

答案 2 :(得分:0)

您的错误源于Python在__前添加变量名时执行的名称修改。如果你只使用没有双尾下划线的名称,这可以正常工作:

class Animal():
    def __init__(self, name , sound):
        self._name= name
        self._sound = sound 
    def ToString(self):
        print ("The {} has the sound  {}".format(self._name ,
                                                self._sound))


cat = Animal('Tiger' , 'roars')
cat.ToString()


class Panther(Animal):

    def __init__(self , name ,sound ,owner):
        self._owner = owner
        super(Panther ,self).__init__(name, sound)
    def ToString(self):
        print(self._owner)
        print(self._name)

并打印出来:

>>> leopard = Panther('Leopard' , 'roars' , 'Senegal')
>>> leopard.ToString()
The Tiger has the sound  roars
Senegal
Leopard