• 硕杨Sxuya
    2018-10-01
    【严重质疑这一讲的super()讲法】【严重质疑这一讲的super()讲法】【严重质疑这一讲的super()讲法】!!!!

    使用方法完全没有讲明白,关键的 super().__init__() 后面一个括号里面的内容由于设计的问题,完全乱了!!!!

    后面一个括号传入的是参数值,放到父类去赋值,是有顺序要求的!!!有顺序要求的!!!

    super().__init__(name) 不是视频里老师带过没有讲明白的意思,如果按照视频里面的表达,代表的意思是“将name初始化”。错的!!!!正确的解读应该是“把输入的name值(按照排列的顺序)传入到父类去进行初始化”!!!

    比如
    class Monster():
        def __init__(self, name, hp=10011):
            self.name = name
            self.hp = hp

    class Boss(Monster):
        '定义boss的内容,Monster的子类'
        def __init__(self, name, level, hp=101):
            super().__init__(hp)
            self.level = level

    boss_10 = Boss(name='boss_10', level='99级', hp=900)
    代表的意思是:把900(不是默认值)当作第一个参数值传入父类,而父类第一个属性是name,所以这个子类的实例的name就是900了。

    比如:
    class Boss(Monster):
        '定义boss的内容,Monster的子类'
        def __init__(self, name, level, hp=101):
            super().__init__(name,hp)

    那么name还是name的值,hp还是hp的值。

    但是,如果是:
    class Boss(Monster):
        '定义boss的内容,Monster的子类'
        def __init__(self, name, level, hp=101):
            super().__init__(hp, name)
    那么,name就是hp位置的值,hp就是name位置的值

    这一个知识点讲得真的不行。多个参数的东西,怎么能只讲解一个就完事了呢?有顺序的知识不讲,很费解呀!!!
    展开

    作者回复: 思考的非常细致,非常好,因为有很多条留言,我在这条集中回答一下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、钻石继承、新式类的知识和原理

    
     8
  • ypine
    2019-04-15
    有个新问题
    文件A:
    # --*-- coding:utf-8 --*--
    class Dog():
        def __init__(self, name, age):
            self.name = name
            self.age = age

        def run(self):
            print('%s can run' % self.name.title())

        def info(self):
            print('%s is %s years old' % (self.name.title(), self.age))

        def up_age(self, upage):
            if upage > 0:
                print('%s is now %s years old' % (self.name, upage + self.age))

        def gas_age(self, gasage):
            if gasage > self.age:
                self.age = gasage - self.age
                print('%s is %s years old' % (self.name.title(), self.age))
            elif gasage < self.age:
                print('%s is %s years old' % (self.name.title(), gasage - self.age))
            else:
                print('%s is %s years old' % (self.name.title(), gasage - self.age))


    class Hashiqi(Dog):
        def __init__(self, name, age, ceyes='blue'):
            super().__init__(name, age)
            self.ceyes = ceyes

        def info1(self):
            print('%s is %s years old, and has %s eyes' % (self.name, self.age, self.ceyes))


    if __name__ == '__main__':
        cat = Dog('apple', 11)
        cat.run()
        cat.info()
        cat.up_age(1)


        print('\n')
        hsq = Hashiqi('jiangzi', 6, 'yellow')
        hsq.info()
        hsq.gas_age(5)
        hsq.info1()

    执行A都正常

    文件B:
    import 文件A

    cat =Dog('hasq',111)
    cat.info()
    cat.gas_age(11)
    dog1=Hashiqi('hahaha',90,'yellow')
    dog1.info1()
    报错 AttributeError: 'Hashiqi' object has no attribute 'info1'

    求老师解答一下
    展开
    
     2
  • space
    2018-11-18
    老师,请教个问题,子类不是可以自动继承父类的属性和方法吗,什么还要使用super调用父类的属性?

    作者回复: 为了照顾初学者,我在视频里没有引入多继承的内容,所以造成了你现在的困惑,由于多类继承不是只字片语能说清楚的,我把相关原理和你介绍一下,更具体的内容你可以通过搜索引擎找到答案。
    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/

    
     1
  • 硕杨Sxuya
    2018-09-30
    继承,主要继承的是方法,属性是没有继承的?

    属性值使用super进行优化后,默认值又是怎么确定的呢?是子类的还是父类的?应该是子类的覆盖了父类的。

    那么,super的作用:减少资源的浪费。这一点有怎么理解呢?是属性初始化这一过程很麻烦、消耗很大,而给属性赋值是很节省的?
    
     1
  • 硕果阳光
    2020-01-02
    老师好 这里面讲的多态和Java的概念类似么?

    作者回复: 是有区别的,python是动态语言,动态语言调用类的方法不检查类型,只要方法在,参数对就可以调用,如果子类没有这个方法,会去父类查找

    
    
  • 倡印
    2019-12-25
    为什么输出会带None ?
     1
    
  • ypine
    2019-04-15
    我使用from A import * 解决 no attribute问题
    
    
  • 永降不息之雨
    2019-03-06
    老师
    报错:NameError: name 'updateName' is not defined

    该怎么解决啊
    
    
  • ypine
    2019-01-31
    定义好父类A,属性有name和hp,子类B继承父类时,同时有自己的新属性,怎么显示B类实例化后的具体信息?

    作者回复: 试试用dir()

    
    
  • 摇之
    2018-12-16
    老师,面向对象三大特征:多态,抽象,封装。抽象在python里是怎么体现的?

    作者回复: python也有一个和java类似抽象类,需要通过abc模块实现。
    import abc
    class My(metaclass=abc.ABCMeta):

    
    
  • 深白浅黑
    2018-11-24
    1、在多父类继承情况下,__init__()会从多个父类进行继承,那该如何选择初始化哪个父类的__init__函数。
    2、在多次继承的情况下,比如父类有whoami()函数,父类的父类也有whoami()函数,子类如果使用whoami()函数,会使用哪个层次的调用,可控吗?

    作者回复: 虽然这两个问题超过了我们的课程内容,但是这两个问题真的相当棒,为你的认真思考点赞。在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

    
    
  • 硕杨Sxuya
    2018-09-30
    【属性的继承】完全凌乱了(┬_┬)

    代码如下:

    class Monster():
        def __init__(self, name, hp=10010):
            self.name = name
            self.hp = hp
        def move(self):
            print('我移动到了……(简写)')
        def ask(self):
            print('%s ask:"who am I?"(父类的话)'%(self.name))

    class Boss(Monster):
        '定义boss的内容,Monster的子类'
        def __init__(self, name, level, hp=101):
            super().__init__(name)
            self.level = level
            super().__init__(hp)

        def ask(self):
            print('%s ask:"whick one to be ated first among you?"(子类的话)'%self.name)

    boss_10 = Boss('boss_10', '99级', 900)
    print(boss_10.hp)
    print(boss_10.level)
    print(boss_10.name)
    boss_10.move()
    boss_10.ask()

    而得到的结果全都混乱了:给定值却使用了默认值、名字的数据给到了hp。。。如下:

    10010
    99级
    900
    我移动到了……(简写)
    900 ask:"whick one to be ated first among you?"(子类的话)

    希望得到解答!
    展开
    
    
  • 硕杨Sxuya
    2018-09-30
    题一个问题,值搜到识别“类的名字”,没有搜到:

    能不能不定义,直接调用实例化后,那个实例的名字呢、而不用输入一个属性值?就像 装饰器那节课讲解的的,获取函数的名字,可以直接使用:```functionExample.__name__,就可以获得函数名字作为 str 传入。那实例的名字能类似直接获取使用么?
    
    
  • 硕杨Sxuya
    2018-09-30
    老师,上面那个问题不用了,想明白、改出来了,提示的意思想明白了点,就是直译的。。。要把有默认值的属性放在没有默认的属性的后面。真的汗😅
    
    
  • 硕杨Sxuya
    2018-09-30
    class Boss(Monster):
    ---'定义boss的内容,Monster的子类'
    ---def __init__(self, hp=90, level):
    ------self.level = level
    ------super().__init__(hp)

    boss_99 = Boss(900, 99)
    print(boss_99.hp)
    print(boss_99.level)
    print(boss_99.move())

    ---
    为什么会弹出如下错误提示:

    SyntaxError: non-default argument follows default argument

    但是我把 level 这个去掉,父类hp有默认值,子类hp也有默认值,就不会报错呢?
    展开
    
    
我们在线,来聊聊吧