小结

什么是继承:
    ---是一种新建类的方式,继承了一个类,类中的属性和方法就在子类中
    --父类/基类
    --子类/派生类
    --新式类:只要继承了object类,就是新式类,再python3中,默认继承object类
        -Python3中:默认继承object
            class A:
                pass
        -python2中,需要显示的指定继承object
    --经典类:没有继承object的类,就是经典类
        -python3中没有经典类
        -python2中才有

使用继承减少冗余

# class Person:
#     school = 'oldboy'
#
# class Teacher(Person):
#     def __init__(self, name, age, level):
#         self.name=name
#         self.age=age
#         self.level=level
#
# teach1=Teacher('铁蛋',18,'S')
# print(teach1.school) #oldboy
#
# class Student(Person):
#     def __init__(self, name, age, course):
#         self.name=name
#         self.age=age
#         self.course=course
#
# stu1=Student('二狗', 18, "python")
# stu1.school='xxx'
# print(stu1.school)#xxx
# 属性的查找顺序: 先找对象---->再到类中找---->再到父类中找--->没有报错

# class Person:
#     school='oldbor'
#
#     def __init__(self,name,age):
#         self.name=name
#         self.age=age
#
# class Teacher(Person):
#     pass
#
# class Student(Person):
#     pass
#
# # 类实例化会自动调用__init__如果类中没有,去父类中找
# stu1=Student('nick',18)
# print(stu1.school)#oldbor
# stu1.school='xxx'
# print(stu1.school) #xxx  进行修改

# 多层继承
# class A:
#     a='AAA'
#
# class B:
#     a='BBB'
#
# class C:
#     a='CCC'
#
# class D(C):
#     #a='DDD'
#     pass
#
# d=D()
# #print(d.a) #DDD
# print(d.a) #CCC
# 多层继承,先从自身找,自身没有再到父类找,父类没有再往父类的父类找,找到结束,没有就报错


#多继承
# class A:
#     a='AAAA'
#
# class B:
#     a='BBB'
#
# class C:
#     a='CCC'

# class D(A,B,C):
#     #a='DDD'
#     pass

#d=D()
#print(d.a)#DDD

#print(d.a)#AAAA
# class D(B,A,C):
#     pass
# d=D()
#print(d.a)#BBB
#多继承会从继承的父类从左到右依次寻找,找到结束,找不到报错

#继承类的菱形问题:新式类和经典类的查找顺序是不一样的
#新式类的查找属性:广度优先
#经典类:深度优先

#继承的菱形问题(显示的都是继承一个类,不是object类):新式类和经典类的查找顺序是不一样的
#新式类(py3中都是新式类):广度优先---从左侧开始,一直往上找,找到菱形的顶点结束(不包括菱形顶点),继续下一个继承的父类往上找,同上,直到最后找到菱形顶点
#经典类(只有py2中才有):深度优先:---从左侧开始,一直往上找,找到菱形顶点结束(包括菱形顶点),继续下一个父类往上找,找到菱形顶点结束(不包括菱形顶点——)

#不出现菱形问题:正常查找


重用父类方法一

# 继承重用父类方法方式一:指名道姓的使用
#跟继承没有关系

class A:
    def __init__(self,name,age):
        self.name=name
        self.age=age
class Person:
    school = 'oldboy'
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def study(self):
        print('study...')

class Teacher(Person):
    def __init__(self,name,age,level):
        A.__init__(self,name,age)#指名道姓的使用

class Student(Person):
    school='oldbody'
    def __init__(self,name,age,course):
        Person.__init__(self,name,age)#指名道姓的使用
    def study(self):
        Person.study(self)
        print("%s学生在学习 "%self.name)#指名道姓的使用
stu1=Student('二蛋',19, 'python')
print(stu1.school)#oldbody
stu1.study()#二蛋学生在学习


重用父类使用方法二

#继承重用父类方法二:通过super关键字
#跟继承就有关系

class Person:
    school='oldboy'
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def study(self):
        print('study...')

class Student(Person):
    school='oldboy'
    def __init__(self,name,age,course):
        #super()按照mro列表拿到父类对象
        #对象来调用绑定方法,不需要传递第一个参数
        super().__init__(name,age)#(py3)都这样写
        #经典类和新式类
        #经典类需要这样写 super(Stuudent,self).__init__(name,age)
        self.course=course
    def study(self):
        super().study()
stu1=Student('二狗',18,'python')
stu1.school='xxx'#修改
print(stu1.school)#xxx
stu1.study()#study...

super的使用

#回顾绑定方法
class Student:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def study(self):
        print(self.name)
        print('study...')
    def change_name(self,new_name):
        self.name=new_name

#修改学生姓名
stu1=Student('nick',19)
#方式一:对象属性直接修改
stu1.name='tank'
print(stu1.name)
#方式二:对象调用方法修改
stu1.change_name('tank')
print(stu1.name)

#方法三:类调用方法修改
Student.change_name(stu1,'二蛋')
print(stu1.name)

#方法四:
#定义一个函数
#def change_name(obj,name):
#     # 修改obj对象的name属性
#     print('原来的名字是%s' % obj.name)
#     obj.name=name
#     print('修改的名字是%s' % obj.name)
#1.name)

#总结:有继承关系的时候,通常用super()
#没有继承关系的时候用指名道姓
#如果继承了多个父类,super是按照列表找,现在想指名道姓的用某个父类的方法就需要指名道姓的使用