Python之继承

一、继承介绍

1 什么是继承

继承是一种新建类的方式,新建的类称之为子类,被继承的类称之为
父类、基类、超类

python支持多继承

2 为何要继承

子类会遗传父类的属性,所以继承是用来解决类与类之间代码冗余问题

3、如何实现继承

class Parent1:  # 定义父类
	pass


class Parent2:  # 定义父类
	pass


class Sub1(Parent1):  # 单继承
	pass


class Sub2(Parent1, Parent2):  # 多继承
	pass

通过类的内置属性 base 可以查看类继承的所有父类

print(Sub1.__bases__)
print(Sub2.__bases__)
# 在python2中:
# 经典类:没有显式的继承object的类,以及该类的子类都是经典类
# 新式类:显式的继承object的类以及该类的子类,都是新式类

# 在python3中:统一都是新式类

# Ps:object类提供了一些常用内置方法的实现, 用来打印对象时返回字符串的内置方法_str_

# 要找出类与类hi见的继承关系,需要先抽象,再继承。抽象即总结相似之处,总结对象之间的相似之处得到类,总结类鱼类之间的相似之处就可以得到父类。
# 字类可以继承/遗传父类所有的属性,因而继承可以用来解决类与类之间的代码重用性问题

按照定义Student类的方式再定义一个Teacher类的继承案列:

class OldboyPeople:
	school = "oldboy"


class Student(OldboyPeople):
	def __init__(self, name, age, gender, stud_id, course):
		self.name = name
		self.age = age
		self.gender = gender
		self.stu_id = stud_id
		self.course = course

	def choose(self):
		print('%s 正在选课' % self.name)


class Teacher(OldboyPeople):
	def __init__(self, name, age, gender, salary, level):
		self.name = name
		self.age = age
		self.gender = gender
		self.salary = salary
		self.level = level

	def score(self, stu, num):
		stu.num = num


stu1 = Student("艾利克斯", 73, 'male', 1001, "python全栈开放")
tea1 = Teacher("egon", 18, 'male', 2000, 10)

print(stu1.school)

二、在子类派生的新方法中重用父类的功能方式一

# 在子类派生的新方法中重用父类的功能
# 方式一:指名道姓地调用某一个类的函数
# 特点:不依赖于继承关系
#
class OldboyPeople:
    school = "oldboy"
    #             空对象,"艾利克斯",73,'male'
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender

    def f1(self):
        print('1111111')

class Student(OldboyPeople):
    #            空对象,"艾利克斯",73,'male',1001,"python全栈开放"
    def __init__(self,name,age,gender,stu_id,course):
        OldboyPeople.__init__(self,name,age,gender)  # OldboyPeople.__init__(空对象,"艾利克斯",73,'male')
        self.stu_id = stu_id
        self.course = course


    def choose(self):
        print('%s 正在选课' %self.name)

    def f1(self):
        OldboyPeople.f1(self)
        print("22222")

class Teacher(OldboyPeople):
    def score(self,stu,num):
        stu.num = num


stu1=Student("艾利克斯",73,'male',1001,"python全栈开放")
tea1=Teacher("egon",18,'male',2000,10)


stu1.f1()

三、属性查找

# 有了继承关系,对象再查找属性是,先从对象自己的_dict_中找,如果没有则取子类中找,然后再去父类中找


# obj.f1()会在父类Foo中找到f1,先打印Foo.f1,然后执行到self.f2(),即obj.f2(),仍会按照:
# 对象本身-》类Bar-》父类Foo的顺序依次找下去,再类Bar中找到f2,因而打印结果位Foo.f2
# 例1:
# class Foo:
#     def f2(self):
#         print("Foo.f2")
#
#     def f1(self):
#         print('Foo.f1')
#         self.f2()  # obj.f2()
#
#
# class Bar(Foo):
#     def f2(self):
#         print("Bar.f2")


# obj = Bar()  # Foo.f1
# obj.f1()  # Bar.f2


# 例2:父类如果不想让子类覆盖自己的方法,可以在方法名前加前缀__设置位私有的
class Foo:
    def __f2(self):  # _Foo__f2
        print("Foo.f2")

    def f1(self):
        print('Foo.f1')
        self.__f2()  # obj._Foo__f2()


class Bar(Foo):
    def __f2(self):  # _Bar__f2
        print("Bar.f2")

obj = Bar()

obj.f1()

四、继承的实现原理

1)补充知识:

新式类:但凡是继承了object类的子类,以该子类子子孙孙类都称之为新式类
经典类:没有继承了object类的子类,以该子类子子孙孙类都称之为经典类

python3中全都是新式类,python2中才有经典类:

在python3中没有继承任何类的类会默认继承object类
class Foo(object):
    pass

print(Foo.__bases__)  # (<class 'object'>,)

2)继承的实现原理

2.1 菱形问题:一个子类继承的多条件分支最终汇聚到一个非object类,在菱形继承下
新式类与经典类关于属性查找的方式不同

新式类:广度优先
经典类:深度优先

python都会计算出一个方法解析顺序(MRO)列表,该列表就是一个简单的所有基类的线性顺序列表


python会再MRO列表上从左到右开始查找基类,只导找到第一个匹配这个属性的类为止。而这个MRO列表的构造时通过一个C3线性化算法来实现的,我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循三条准则:
1、子类会先于父类被检查
2、多个父类会根据他们再列表中的顺序被检查
3、如果对下一个类存在两个合法的选择,选择第一个父类

所以obj.test()查找顺序时先从对象obj本身的属性里找方法test,没有找到,则参照属性查找的发起者,所处类D的MRO列表来一次检索,首先在类D中未找到,然后再B中找到方法test

ps:
1、由对象发起的属性查找,会从对象自身的属性里检索,没有则会按照对象的类.mro()规定的顺序依次找下去
2、由类发起的属性查找,会按照当前类.mro()规定的顺序依次找下去

五、深度和广度优先

如果继承关系位菱形结构,那么经典类和新式类会有不同的MRO,分别对应属性的两种查找方式:深度优先和广度优先
例1:非菱形继承,经典类与新式类的属性查找顺序都一样
class E:
    # def test(self):
    #     print('from E')
    pass

class F:
    def test(self):
        print('from F')


class B(E):
    def test(self):
        print('from B')
    pass

class C(F):
    def test(self):
        print('from C')


class D:
    def test(self):
        print('from D')


class A(B, C, D):
    def test(self):
        print('from A')
    pass

obj=A()
obj.test()

# 例2:菱形继承
class G(object): # 在python2中,未继承object的类及其子类,都是经典类
    def test(self):
        print('from G')
    pass

class E(G):
    def test(self):
        print('from E')
    pass

class F(G):
    def test(self):
        print('from F')
    pass

class B(E):
    def test(self):
        print('from B')
    pass

class C(F):
    def test(self):
        print('from C')
    pass

class D(G):
    def test(self):
        print('from D')
    pass

class A(B,C,D):
    def test(self):
        print('from A')
    pass

obj=A()
obj.test()


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值