Day09 - 子类父类多继承多层继承多态

1. 子类中访问父类中的私有属性和私有方法

如果想使用父类中的私有属性和私有方法,那么就需要在父类中,为这些私有的属性和方法,提供相应的公有的接口方法来间接访问

2. 如何为父类中的属性进行初始化

在子类中如果定义了自己的初始化方法,那么这时父类的初始化方法就不会再执行了
那么就导致父类中定义的属性无法初始化,子类对象就无法使用继承自父类的属性
如果想正常初始化,需要在子类的初始化方法中,手动调用父类的初始化方法
现阶段调用格式:
父类名.__init__(self,父类中需要属性参数列表)
'''
子类初始化父类的属性
'''

# 父类
class Father(object):
    def __init__(self,name):
        print('Father Init Run ...')
        self.name = name


# 子类
class Son(Father):
    def __init__(self,name, age):
        # 因为子类提供了 init 方法后,那么在使用子类实例对象时,就会调用 子类自己 init 方法,
        # 那么就不会再调用 父类的init方法了,父类当中的属性就不会有绑定的机会,所以这时是没有父类的属性的
        # 如果想父类中的属性可以得到,需要执行父类中的init方法
        # 父类名.init()
        Father.__init__(self, name)
        print('Son Init run ..')
        self.age = age



# 测试
s = Son('Tom', 12)
print(s.name)
print('age:', s.age)

3. 子类中重写和调用父类的方法

在子类继承父类时,子类会拥有父类中的方法.
但是子类并不需要或不满足父类方法中提供的功能,这时就需进行对父类方法重写

重写之后,调用该方法时,执行谁?
答案: 调用重写后子类中的方法
'''
子类重写父类中的方法
'''


# 父类
class Father(object):
    # 实现一个治病
    def cure(self):
        print('父类是个老中医,使用中医古法治病')


# f = Father()
# f.cure()

# 子类
class Son(Father):
    # 子类也是一个大夫,也有治病的功能
    def cure(self):
        # 直接使用 父类名.方法名 形式来引用父类的功能
        Father.cure(self)
        print('子类出国深造,学成以后,使用中西医结合方法治病')


s = Son()
s.cure()

4. 子类方法中调用父类的同名方法

子类调用父类同名方法,第一种方法是:指名道姓,重新在子类中将每个父类方法调用一遍,这种方法代码冗余,但是有多继承的话,也能解决问题;第二种方法是:使用super代替父类的名字调用父类,因此要调用爷爷类的同名方法,那就要在父类中同样使用super代替,所以说super方法比较适合单一继承。

#  super无参数写法
super().__init__()
super().要调用的函数()

5. 多层继承

继承关系有多层,祖孙三代

查找方法:

父类名.方法名(self)
'''
多层继承
'''


class A(object):
    def a(self):
        print('a function')


class B(A):
    def b(self):
        print('b function')


class C(B):
    # C类中重写了B类中的方法
    def b(self):
        B.b(self)
        print('b in C function')

    def c(self):
        print('c function')


class D(C):
    def d(self):
        print('d function')


# 测试
d = D()
d.a()
d.b()
d.c()
d.d()
'''
多层继承
'''


class A(object):
    def __init__(self, a):
        self.a = a


class B(A):
    def __init__(self, a, b):
        A.__init__(self, a)
        self.b = b


class C(B):
    def __init__(self, a, b, c):
        B.__init__(self, a, b)
        self.c = c


class D(C):
    def __init__(self, a, b, c, d):
        C.__init__(self, a, b, c)
        self.d = d


# 测试
d = D(1, 2, 3, 4)
print(d.a)
print(d.b)
print(d.c)
print(d.d)

d.__dict__#保存信息到字典
D.__dict__

6. 多继承

格式:
class 类名(父类名1,.....):
	pass
'''
多层继承:纵向
多继承: 横向

'''


# 定义一个父亲类
class Father(object):
    def func_fa(self):
        print('Father Function ...')


# 定义一个母亲类
class Mother(object):
    def func_mo(self):
        print('Mother function ...')


# 上面的两个类,有一个共同子类
class Son(Father, Mother):
    def play(self):
        print('Son play...')


# 测试
s = Son()
s.play()
s.func_fa()
s.func_mo()

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

7. 多继承的初始化

'''
多继承的初始化问题
'''


# 定义一个人类
# 在这种 继承关系 上,这个共同的父类 Person 会被初台化多次,这是继承时的问题
# 是否 父类名调用 实始化方法的时候 引起的
class Person(object):
    def __init__(self, aaa):
        print('Person Init ...')
        self.aaa = aaa


class Father(Person):
    def __init__(self, aaa, name):
        Person.__init__(self, aaa)
        print('Father Init ...')
        self.name = name


class Mother(Person):
    def __init__(self, aaa, age):
        Person.__init__(self, aaa)
        print('Mother Init ...')
        self.age = age


class Son(Father, Mother):
    def __init__(self, aaa, name, age, gender):
        Father.__init__(self, aaa, name)
        Mother.__init__(self, aaa, age)
        print('Son Init ...')
        self.gender = gender


# 测试
s = Son(1, 'Tom', 12, '男')
print(s.aaa)
print(s.name)
print(s.age)
print(s.gender)

'''
多继承的初始化问题的解决
'''


# 定义一个人类

class Person(object):
    def __init__(self, aaa):
        print('Person Init ...')
        self.aaa = aaa


class Father(Person):
    def __init__(self, aaa, name, age):
        super(Father, self).__init__(aaa, age)
        print('Father Init ...')
        self.name = name


class Mother(Person):
    def __init__(self, aaa, age):
        super(Mother, self).__init__(aaa)
        print('Mother Init ...')
        self.age = age


class Son(Father, Mother):
    def __init__(self, aaa, name, age, gender):
        # 参数二是当前类的实例对象
        # 参数一是当前类名
        # 在参数二对象的所属类的mro关系 中找参数一的下一个类进行实始化
        super(Son, self).__init__(aaa, name, age)
        print('Son Init ...')
        self.gender = gender


# 测试
s = Son(1, 'Tom', 12, '男')
print(s.aaa)
print(s.name)
print(s.age)
print(s.gender)

print(Son.__mro__)
'''
这个顺序关系是解释器在执行代码 时,自动确认的我们无法干涉
(<class '__main__.Son'>,
 <class '__main__.Father'>, 
 <class '__main__.Mother'>, 
 <class '__main__.Person'>, 
 <class 'object'>)
'''

# f = Father('tom',1)
print(Father.__mro__)

父类名调用  理解
super()调用  使用
super(类名,self) 了解 
'''
多继承的初始化问题的解决
'''


# 定义一个人类

class Person(object):
    def __init__(self, aaa):
        print('Person Init ...')
        self.aaa = aaa


class Father(Person):
    def __init__(self, name, *args):
        # super(Father, self).__init__(*args)
        super().__init__(*args)
        print('Father Init ...')
        self.name = name


class Mother(Person):
    def __init__(self, age, *args):
        # super(Mother, self).__init__(*args)
        super().__init__(*args)
        print('Mother Init ...')
        self.age = age


class Son(Father, Mother):
    def __init__(self, gender, name, age, aaa):
        # 参数二是当前类的实例对象
        # 参数一是当前类名
        # 在参数二对象的所属类的mro关系 中找参数一的下一个类进行实始化
        # super(Son, self).__init__(name,age,aaa)
        super().__init__(name, age, aaa)
        print('Son Init ...')
        self.gender = gender


# 测试
# s = Son(1, 'Tom',12,'男')
s = Son('男', 'Tom', 12, 1)
print(s.aaa)
print(s.name)
print(s.age)
print(s.gender)

print(Son.__mro__)
'''
这个顺序关系是解释器在执行代码 时,自动确认的我们无法干涉
(<class '__main__.Son'>,
 <class '__main__.Father'>, 
 <class '__main__.Mother'>, 
 <class '__main__.Person'>, 
 <class 'object'>)
'''

f = Father('Jack', 2)
print(f.aaa)
print(f.name)
print(Father.__mro__)
super执行过程:
在 self 这个对象的所属类中,通过 __mro__ 找到方法解析顺序
在顺序中,找当前类名的下一个类来初始化或查找方法
'''
类的继承书写顺序会影响mro顺序
'''


class A(object):
    pass


class B(A):
    pass


class C(A):
    pass


# class D(B,C):
# (<class '__main__.D'>, < class '__main__.B' >, < class '__main__.C' >, < class '__main__.A' >, < class 'object' > )

class D(C, B):
    # (<class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
    pass


print(D.__mro__)

在多继承时,如果继承的多个类同时继承同一个父类,那么这时会出现初始化问题
这个共同父类会被初始化多次.

类名.__mro__ 得到了一个元组,元组中的元素是当前类在继承关系上的一个顺序

方法解析顺序
method relational ordered

这个顺序不是我们确定的,是由在确定某个类的继承关系关系后,由解释器来确定这个顺序
'''
多重多继承时,方法的查找顺序也参考MRO
'''


class A(object):
    def show(self):
        print('A _ Show Run ...')

    def info(self):
        print('A - Info run ...')


class B(A):
    def show(self):
        print('B _ Show Run ...')


class C(A):
    def show(self):
        print('C _ Show Run ...')

    def info(self):
        # super().info()
        # A.info(self)
        print('C - Info run ...')


class D(B, C):
    def show(self):
        super().show()
        A.show(self)
        print('D _ Show Run ...')


d = D()
d.show()
d.info()

super对象是基于类的mro顺序来对当前类进行初始化的
基于这个mro顺序可以保证,所有的继承关系的上类,都只执行一次
'''
多继承的初始化问题的解决
'''


# 定义一个人类

class Person(object):
    def __init__(self, aaa):
        print('Person Init ...')
        self.aaa = aaa


class Father(Person):
    def __init__(self, name, *args):
        super(Father, self).__init__(*args)
        print('Father Init ...')
        self.name = name


class Mother(Person):
    def __init__(self, age, *args):
        super(Mother, self).__init__(*args)
        print('Mother Init ...')
        self.age = age


class Son(Father, Mother):
    def __init__(self, gender, name, age, aaa):
        # 参数二是当前类的实例对象
        # 参数一是当前类名
        # 在参数二对象的所属类的mro关系 中找参数一的下一个类进行实始化
        super(Son, self).__init__(name, age, aaa)
        print('Son Init ...')
        self.gender = gender


# 测试
# s = Son(1, 'Tom',12,'男')
s = Son('男', 'Tom', 12, 1)
print(s.aaa)
print(s.name)
print(s.age)
print(s.gender)

print(Son.__mro__)
'''
这个顺序关系是解释器在执行代码 时,自动确认的我们无法干涉
(<class '__main__.Son'>,
 <class '__main__.Father'>, 
 <class '__main__.Mother'>, 
 <class '__main__.Person'>, 
 <class 'object'>)
'''

f = Father('Jack', 2)
print(f.aaa)
print(f.name)
print(Father.__mro__)
mro -> 一个类的继承书写顺序会影响mro顺序

8. 多继承调用指定父类中方法

	父类名.方法()
	super().方法()

9. 多态

多种形态
程序中的意义:
	当调用一个方法名的时候,得到的结果不同
	在一般的面向对象语言中,多态是由继承来实现的
	但是在python中,python,天生具有多态性


鸭子类型: Duck Typing
	一只鸟如果长的鸭子,叫声像鸭子,那么就认为它就是鸭子
'''
多态
'''


# 标准多态

class Father(object):
    def cure(self):
        print('老中医使用中医治病')


class Son(Father):
    def cure(self):
        print('小大夫使用中西医结合治病')


class Dog(object):
    def bark(self):
        print('Won won ...')


class AnimalDoctor(object):
    def cure(self):
        print('我是个兽医,主要给动物治病,但是也能给人凑合治一下')


# 病人类
class Person(object):
    # 需要一个大夫给他治病
    def need_doctor(self, doctor):
        doctor.cure()


# 测试
p = Person()

p.need_doctor(Father())
p.need_doctor(Son())
# p.need_doctor(Dog())
p.need_doctor(AnimalDoctor())

10. 实例对象属性和实例对象方法

以 对象名.xxx  的形式调用的都是实例的属性或实例的方法
'''
实例属性和实例 方法
'''


class Cat(object):
    def __init__(self, name):
        # 定义一个实例 属性
        self.name = name

    # 定义了一个实例方法
    def info(self):
        print(self.name)

    def show(self):
        print('Show Run :')
        self.info()


# 测试
tom = Cat('Tom')
# 使用实例属性
print(tom.name)
# 使用实例方法
tom.info()
tom.show()

# Python中万物皆对象
# print(Cat.name)
Cat.show()

# 结论:
# 为什么类名不能调用 实例 对象属性和实例对象方法呢?
# 因为类对象存在时,不一定有实例对象存在
# 实例属性和实例 方法只能由实例对象调用

​ 实例属性和实例方法只能由实例对象调用

11. 类对象和类属性

类属性可以使用实例对象来引用,但是不能修改
一般情况下:类属性 都只使用 类对象 来调用

类对象.类属性
'''
类对象和类属性
'''


class ClassRoom(object):
    # 当定义一个类属性时,相当于这个类中的全局变量
    # 该类的所有对象都 可以使用该 类属性
    # 可以在所有的对象间进行数据共享
    center_kong_tiao = '格力空调'

    # 实例方法
    def show(self):
        print('实例方法中去访问类属性:')
        print(ClassRoom.center_kong_tiao)


cr901 = ClassRoom()
print(cr901.center_kong_tiao)

cr902 = ClassRoom()
print(cr902.center_kong_tiao)

cr903 = ClassRoom()
print(cr903.center_kong_tiao)

# cr901.center_kong_tiao = '海尔空调'
ClassRoom.center_kong_tiao = '海尔空调'
print(cr901.center_kong_tiao)
print(cr902.center_kong_tiao)
print(cr903.center_kong_tiao)

cr901.show()

扩展

'''
扩展:属性和方法的保存位置
'''

class Cat(object):
    def __init__(self,name):
        self.name = name
        self.__age = 1

    def public_method(self):
        print('公有的对象方法')

    def __private_method(self):
        print('私有的对象方法')


tom = Cat('Tom')
jack = Cat('Jack')
# __dict__ 是一个魔法属性,用来保存当前对象的所有的成员
print(Cat.__dict__)
print(tom.__dict__)
print(jack.__dict__)

tom.public_method()

Cat.public_method(tom)
Cat.public_method(jack)

def display():
    print('Display')

display()
posted @ 2023-01-23 18:36  李好秀  阅读(46)  评论(0编辑  收藏  举报