子类没有正确地从超类继承结构[重复]

Posted

技术标签:

【中文标题】子类没有正确地从超类继承结构[重复]【英文标题】:Subclass not inheriting structure from superclass properly [duplicate] 【发布时间】:2017-11-12 17:52:14 【问题描述】:

我刚开始使用 Python,但我无法弄清楚为什么我在使用如此简单的类继承时会遇到问题,尽管我一直在关注本教程的常见用法,但我还没有看到任何人其他在 Stack Overflow 上遇到此问题。这是代码(别担心,没什么复杂的):

import random
import sys
import os

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

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

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

cat = Animal ('Whiskers', 33, 10, 'meow')
print(cat.toString())

bird = Animal ('Flutie', 33, 10, 'tweet')
print(bird.toString())

class Dog(Animal):

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

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

spot = Dog ('Spot', 53, 27, "Woof")

print(spot.toString())

...这是输出:

Whiskers is 33 cm tall and 10 kilograms and says meow
Flutie is 33 cm tall and 10 kilograms and says tweet
Traceback (most recent call last):
  File "C:/.../animal_test.py", line 72, in <module>
    print(spot.toString())
  File "C:/.../animal_test.py", line 65, in toString
    return " is  cm tall and  kilograms and says ".format(self.__name,
AttributeError: 'Dog' object has no attribute '_Dog__name'

【问题讨论】:

属性名中的双下划线在python中有特殊含义:***.com/questions/1301346/… 除了名称修饰问题之外,在类级别设置__name = '' 等可能不会像您想的那样,在这里没有任何作用,并且可能会导致以后出现问题。跨度> Python != Java。停止编写双下划线名称损坏的属性除非这是你想要的,你正在尝试创建类本地引用,这肯定不是你想要的,因为你正在尝试访问子类中的属性。停止在类级别编写属性,您只会在实例级别进行隐藏,即__name = "" 这几乎肯定不会像您认为的那样做。不要写toString方法,使用__str__ 出于好奇,你在学习什么教程? @PlatypusEgg 我对该教程持高度怀疑态度。只需快速浏览一下,此人就具有教你 Java 中的 Python 的所有经典迹象。他们在条件语句周围使用括号:if (something is something): 。他们使用错误的分号结束行。由于我上面提到的事情,类定义的示例完全不是pythonic。他还教你编写 getter 和 setter,这不是你在 Python 中做的封装。它们可能来自 Java/C++ 。如果您想学习 Python,请获取更好的 Python 教程。 【参考方案1】:

双下划线代表name mangling。

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

解释时直译为:

class Animal:
    def __init__(self, name, height, weight, sound):
        self._Animal__name = name
        self._Animal__height = height
        self._Animal__weight = weight
        self._Animal__sound = sound

无论在哪里调用,或者是谁调用了__init__,前缀_Animal 都会出现,因为它实际上位于Animal 类下。

但是当你在这里使用属性时,因为它物理上位于 Dog 类下,所以得到的名称会变成这样:

class Dog(Animal):

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

    def toString(self):
        return " is  cm tall and  kilograms and says ".format(self._Dog__name,
                                                                      self._Dog__height,
                                                                      self._Dog__weight,
                                                                      self._Dog__sound)

Dog 对象肯定没有self._Dog__name 的属性,而是有self._Animal__name 的属性。

【讨论】:

有趣。从所有属性中删除双下划线使代码工作,所以谢谢。我想我了解名称修改是如何导致问题的。我想我现在唯一的问题是为什么它也适用于我关注的高度可信的教程:youtube.com/watch?v=N4mEzFDjqtA。课程介绍内容从 32 分钟开始。他正在使用 Python 3.4.2 版本... 那个教程不是特别好......他犯了错误,但没有在视频中解释/抓住它。在他的实际代码中,他调用了 getter 函数而不是下划线的属性。 IE。他在他的实际代码中这样做了:self.get_name() 而不是Dog 类的toString 字符串格式中的self.__name() 这是他的代码:newthinktank.com/2014/11/python-programming,向下滚动到定义 Dog 类的位置,注意他的 toString 函数与视频的不同 我打算继续观看教程以开始了解某些方法的一般偏好,但如果有一个你强烈推荐给 Python 初学者(以及一般的非标记编程)的方法,我很想知道。 我是通过阅读大量书籍来学习 python 的 :D 但是官方的 python 教程非常简洁 docs.python.org/3.6/tutorial ,并且代码学院有一个动手教程 codecademy.com/learn/python 。对于视频教程,对不起,我没有任何偏好...

以上是关于子类没有正确地从超类继承结构[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Python子类方法从超类方法继承装饰器

OWL:如何从超类继承两个类之间的属性关系?

Django,Python继承:从超类中排除一些字段

从超类调用子类方法

无法从超类访问 Django 模型的子类

Django模型继承:使用现有超类创建子类