# 1.继承的概念
'''
1.1 什么是继承?
I:继承是一种创建新类的方式,新建的类可称为子类或派生类,父类又可称为基类或超类,子类会遗传父类的属性
II:需要注意的是:python支持多继承,在Python中,新建的类可以继承一个或多个父类
1.2 经典类和新式类
在python2中有经典类与新式类之分
新式类:继承了object类的子类,以及该子类的子类子子类。。。
经典:没有继承object类的子类,以及该子类的子类子子类。。。
print(Parent1.__bases__)
print(Parent2.__bases__)
在python3中没有继承任何类,那么会默认继承object类,所以python3中所有的类都是新式类
经典类
class 类名:
代码
新式类
class 类名(object):
代码
'''
# 2.单继承
# 2.1定义父类
class Parent(object):
def __init__(self):
self.num = 1
def info_print(self):
print(self.num)
return self.num
# 2.2定义子类
class Sub(Parent):
pass
# 2.3创建对象
result = Sub()
# 2.4对象访问实例属性
print(result.num)
# 2.5对象调用实例方法
result.info_print()
# 3.多继承 一个类同时继承多个父类
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class School(object):
def __init__(self):
self.kongfu = '[黑马煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class Prentice(School, Master):
pass
daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()
# ps:当一个类有多个父类的时候,默认使用第一个父类的同名属性和方法。
# 4.子类重写父类的同名属性和方法
# 独创配方
class Prentice1(School, Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
print('子类重写父类的同名属性和方法')
daqiu1 = Prentice1()
print(daqiu1.kongfu)
daqiu1.make_cake()
print(Prentice.__mro__)
# PS:子类和父类具有同名属性和方法,默认使用子类的同名属性和方法。
# 5.子类调用父类的同名属性和方法
class Prentice2(School, Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
def make_cake(self):
# 如果是先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用属性前,先调用自己子类的初始化
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
# 调用父类方法,但是为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
print('子类调用父类的同名属性和方法')
daqiu2 = Prentice2()
daqiu2.make_cake()
daqiu2.make_master_cake()
daqiu2.make_school_cake()
# 6.多层继承
class Tusun(Prentice2):
pass
print('多层继承')
tus1 = Tusun()
tus1.make_cake()
tus1.make_school_cake()
tus1.make_master_cake()
# 7.super()
class Parent(object):
def __init__(self):
self.num = 1
def info_print(self):
print(self.num)
# 2.2定义子类
class Master3(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class Prentice3(Master3):
def __init__(self):
self.kongfu = '[独创煎饼果子技术]'
def make_cake(self):
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
# 子类调用父类的同名方法和属性:把父类的同名属性和方法再次封装
def make_master_cake(self):
Master3.__init__(self)
Master3.make_cake(self)
# 一次性调用父类的同名属性和方法
def make_old_cake(self):
# super().函数()
super().__init__()
super().make_cake()
print('super()')
daqiu = Prentice3()
daqiu.make_old_cake()
# ps:使用super() 可以自动查找父类。调用顺序遵循 `__mro__` 类属性的顺序。比较适合单继承使用。
# 9.属性查找
# 有了继承关系,对象在查找属性时,先从对象自己的__dict__中找,如果没有则去子类中找,然后再去父类中找……
class Foo:
def f1(self):
print('Foo.f1')
def f2(self):
print('Foo.f2')
self.f1() # obj.f1()
class Bar(Foo):
def f1(self):
print('Bar.f1')
b = Bar()
b.f2()
# b.f2()会在父类Foo中找到f2,先打印Foo.f2,然后执行到self.f1(),即b.f1(),仍会按照:对象本身->类Bar->父类Foo的顺序依次找下去,在类Bar中找到f1,因而打印结果为Foo.f1
# 10.私有权限--父类如果不想让子类覆盖自己的方法,可以采用双下划线开头的方式将方法设置为私有的
# 定义私有属性和方法:在属性名和方法名 前面 加上两个下划线 __。
# 获取和修改私有属性值:一般定义函数名`get_xx`用来获取私有属性,定义`set_xx`用来修改私有属性值。
class Foo:
# 定义私有属性
def __init__(self):
self.__money = 2000000
# 定义私有方法
def __f1(self): # 变形为_Foo__fa
print('Foo.f1')
def f2(self):
print('Foo.f2')
self.__f1() # 变形为self._Foo.__fa,因而只会调用自己所在的类中的方法
# 获取私有属性
def get_money(self):
return self.__money
# 修改私有属性
def set_money(self):
self.__money = 500
class Bar(Foo):
def __f1(self): # 变形为_Bar__f1
print('Bar.f1')
b = Bar()
b.f2() # 在父类中找到f2方法,进而调用b._Foo__f1()方法,同样是在父类中找到该方法
# 调用get_money函数获取私有属性money的值
print(b.get_money())
# 调用set_money函数修改私有属性money的值
b.set_money()
print(b.get_money())
# 11.mixins机制
# mixins机制核心:就是在多继承背景下尽可能地提升多继承的可读性
# ps:让多继承满足人的思维习惯=》什么"是"什么
class Vehicle:
pass
class FlyableMixin:
def fly(self):
pass
class CivilAircraft(FlyableMixin, Vehicle): # 民航飞机
pass
class Helicopter(FlyableMixin, Vehicle): # 直升飞机
pass
class Car(Vehicle): # 汽车并不会飞,但按照上述继承关系,汽车也能飞了
pass
# 12.总结
'''
1.什么是继承?
I:继承是一种创建新类的方式,新建的类可称为子类或派生类,父类又可称为基类或超类,子类会遗传父类的属性
II:需要注意的是:python支持多继承,在Python中,新建的类可以继承一个或多个父类
2.经典类和新式类
在python2中有经典类与新式类之分
新式类:继承了object类的子类,以及该子类的子类子子类。。。
经典:没有继承object类的子类,以及该子类的子类子子类。。。
print(Parent1.__bases__)
print(Parent2.__bases__)
在python3中没有继承任何类,那么会默认继承object类,所以python3中所有的类都是新式类
在Python中子类可以同时继承多个父类,在子类继承了多个父类时,经典类与新式类的属性查找顺序不一样:
经典类:深度优先,会在检索第一条分支的时候就直接一条道走到黑,即会检索大脑袋(共同的父类)
新式类:广度优先,会在检索最后一条分支的时候检索大脑袋
3.多继承(一个类同时继承多个父类)
1.多继承的优缺点
优点:子类可以同时遗传多个父类的属性,最大限度地重用代码
缺点:
1、违背人的思维习惯:继承表达的是一种什么"是"什么的关系
2、代码可读性会变差
3、不建议使用多继承,有可能会引发可恶的菱形问题,扩展性变差,
如果真的涉及到一个子类不可避免地要重用多个父类的属性,应该使用Mixins
2.为何要用继承:用来解决类与类之间代码冗余问题
4.继承的特点
子类默认拥有父类的所有属性和方法
子类重写父类同名方法和属性
子类调用父类同名方法和属性
5.super()方法快速调用父类方法
6.通过类的内置属性__bases__可以查看类继承的所有父类
7.继承实现原理
对于定义的每一个类,Python都会计算出一个方法解析顺序(MRO)列表,该MRO列表就是一个简单的所有基类的线性顺序列表
print(Bar.mro()) 新式类内置mro方法可以查看线性列表的内容,经典类没有该内置该方法
Python会基于MRO列表按照从左到右的顺序依次查找基类,直到找到第一个匹配这个属性的类为止。
8.属性查找
对象在查找属性时,先从对象自己的__dict__中找,如果没有则去子类中找,然后再去父类中找……
9.私有权限--父类如果不想让子类覆盖自己的方法,可以采用双下划线开头的方式将方法设置为私有的
定义私有属性和方法:在属性名和方法名 前面 加上两个下划线 __。
获取和修改私有属性值:一般定义函数名`get_xx`用来获取私有属性,定义`set_xx`用来修改私有属性值。
10.mixins机制
mixins机制核心:就是在多继承背景下尽可能地提升多继承的可读性
'''