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()
本文来自博客园,作者:李好秀,转载请注明原文链接:https://www.cnblogs.com/lehoso/p/17065368.html