作者回复: 思考的非常细致,非常好,因为有很多条留言,我在这条集中回答一下super的问题。这里我没有展开讲,因为已经大大超过了初学面向对象能够理解的范围。 我在视频里主要希望同学们能够知道子类调用一个父类可以使用普通方法和super()方法两种方法即可 普通方法是 父类.__init__(self) supter方法是 super(子类, self).__init__() 因为super()的使用这里涉及到一个非常复杂的问题,叫做多重继承,在进行重复调用和多继承的时候就会涉及到你所说的查找顺序(MRO)问题 例如B,C类继承A类,D继承B,C 在初始化D类的时候就会初始化两次A类,python语言的解决的方法就是使用super()方法,来解决这个父类被多次初始化的头疼的问题 其他语言诸如java 禁用了多继承,C++使用虚拟机继承 来解决钻石继承的问题。 因此这里不单单要关注__init__()内的顺序问题,还要先学习mro(method resolution order),掌握super()更内在的功能。才能理解他们的顺序问题 此知识点不做展开了,如果对多继承希望透彻的学习建议先掌握mro、钻石继承、新式类的知识和原理
作者回复: 为了照顾初学者,我在视频里没有引入多继承的内容,所以造成了你现在的困惑,由于多类继承不是只字片语能说清楚的,我把相关原理和你介绍一下,更具体的内容你可以通过搜索引擎找到答案。 Python中类的继承是这样规定的,子类继承父类,子类就有了父类的属性和方法,那么问题来了,在python中类的初始化都是__init__(), 如果子类初始化时没有这个函数,那么它便代用父类的init,如果实现了,那么就会覆盖父类的初始化函数。那我有没有办法声明的时候直接从父类中找方法呢?这就产生了self和super。他们两个的定义是self首先调用自身的方法,如果没有再去父类中找,super是直接从父类中找方法,那你的程序需要后者就需要super()函数了。 super官方的定义是: super有两个典型的用例。在具有单继承的类层次结构中,super可用于引用父类而不显式命名它们,从而使代码更易于维护。这种用法与其他编程语言中super的使用密切相关。 第二个用例是在动态执行环境中支持协作多重继承。此用例是Python独有的,在静态编译语言或仅支持单继承的语言中找不到。这使得实现“钻石继承”成为可能,其中多个基类实现相同的方法。好的设计要求此方法在每种情况下都具有相同的调用签名(因为调用的顺序是在运行时确定的,因为该顺序适应类层次结构中的更改,并且因为该顺序可以包括在运行时之前未知的兄弟类)。 这是官方文档上对super的解释,我把它翻译成了中文,看看这回对super的理解有没有好一些呢?至于钻石继承我在之前的回复中介绍过,就不重复解释了,它的复杂程度也超过了课程设定的目标,有兴趣可以了解一下。关于super()更多的解释可以参考以下文档: https://www.python.org/dev/peps/pep-3135/
作者回复: 这里可以理解成把父类的__init__()在子类 执行一遍,如果父类有__init__()且需要在子类使用,需要增加super这个方法
作者回复: 虽然这两个问题超过了我们的课程内容,但是这两个问题真的相当棒,为你的认真思考点赞。在python中有经典类和新式类两种,我们以新式类为例,依次回答一下你的两个问题 1. 这是多重继承的问题,注意子类定义时圆括号的父类顺序,如果多个父类有相同的方法,并且子类里面没有声明,它会从左至右搜索,结论是子类未定义,按顺序(从左向右)查找父类是否包含该方法,与是不是__init__函数无关。(这里我不先引入super,打乱你的思路,理解了这个概念之后,在搜索引擎再掌握super函数的用法) class FatherA(object): def __init__(self): print("in FatherA") class FatherB(object): def __init__(self): print("in FatherB") class SonC(FatherA, FatherB): pass if __name__ == '__main__': myfunc = SonC() 参考: https://docs.python.org/3/tutorial/classes.html#multiple-inheritance https://stackoverflow.com/questions/3277367/how-does-pythons-super-work-with-multiple-inheritance 2. 这是多层继承的问题,如果子类声明了同名的方法,会覆盖父类的方法,同样的父类声明了方法会覆盖父类的父类声明的方法。 class Father(object): def whoami(self): print("in Father") class Son(Father): def whoami(self): print("in Son") class GrSon(Son): def whoami(self): print("in GrSon") if __name__ == '__main__': myfunc = GrSon() myfunc.whoami() 这里同样不引入super()增加技术负担。我再补充一下多继承还有一个钻石继承的问题。 参考:https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem
作者回复: 1 子类如果不写__init__(),会自动继承父类的__init__() 2 子类如果重写,实例化子类,就不会调用父类的__init__() 3 一般写法: def __init__(self, 参数): super(父类, self).__init__(参数)
作者回复: 检查一下 Monster的类型,参数
作者回复: 是有区别的,python是动态语言,动态语言调用类的方法不检查类型,只要方法在,参数对就可以调用,如果子类没有这个方法,会去父类查找
作者回复: 试试用dir()
作者回复: python也有一个和java类似抽象类,需要通过abc模块实现。 import abc class My(metaclass=abc.ABCMeta):