我正在阅读Python 3面向对象程序设计,但对其中一个示例有些困惑。是ch。 3,第78:

class AudioFile:
    def __init__(self, filename):
        if not filename.endswith(self.ext):
            raise Exception("Invalid file format")
        self.filename = filename

class MP3File(AudioFile):
    ext = "mp3"
    def play(self):
        print("playing {} as mp3".format(self.filename))


因此,MP3File继承自AudioFile。超类AudioFile如何访问self.ext?例如,Java有抽象类,因此不能保证AudioFile可以实例化/具有ext字段。更重要的是,我认为子类继承了超类的所有信息,但没有另一个方向的信息流。

看来我错了...

任何澄清都很好,

克莱曼

最佳答案

没错,我们不能保证AudioFile具有ext属性。如果您要直接实例化AudioFile或编写一个未定义ext的子类并将其实例化,则尝试访问self.ext确实会失败。

因此,您可以将AudioFile视为一个抽象类,因为它依赖于其子类填充详细信息,以便AudioFile本身能够正常工作。但是在Python中,这种抽象性不是由语言编码的;您只需证明人们必须编写定义ext的AudioFile子类,否则他们可能会遇到错误。 (其他一些抽象性也可以由abc模块处理,尽管实际上它们通常也通过文档约定进行处理。)

至于AudioFile如何访问存在的属性。 。 。好吧,它是在实例而不是类上访问它。用MP3File之类的实例化obj = MP3File()后,便有了一个实例对象obj。在该对象上执行obj.ext将返回其ext属性,或者,如果该实例没有其自身的属性,它将在其类中查找该属性(然后在其超类中一直查找)。每次您尝试访问属性时,都会动态发生此属性查找。您不能也不可以“预先声明”将在哪里找到属性(在实例,类或层次结构上的某些超类中)。因此,当同时也是AudioFileMP3File执行self.ext时,它会在MP3File上找到属性,因为selfMP3File的实例。

如果这本书没有解释这方面的任何内容,那么那个例子可能不是最好的例子。它可以工作,但是对于具有不同OO语义的其他语言的用户来说,它的工作方式并不明显。另外,即使您确实了解Python,在现实世界中,使文档告诉您如何使用AudioFile也很重要(即说“您必须对此子类化,并且您的子类必须定义ext)。

关于python - Python中的基本多态性混淆,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31862883/

10-12 19:34