凉城旧巷
Python从入门到自闭,Java从自闭到放弃,数据库从删库到跑路,Linux从rm -rf到完犊子!!!

继承

一、什么是继承

继承是一种创建新类的方式,新建的类可以继承一个或多个父类(python支持多继承),父类又可称为基类或超类,新建的类称为派生类或子类。

二、继承的特点

1.继承描述的是事物的遗传关系,子类可以重用父类的属性

2.在Python中支持一个子类继承多个父类

3.Python类分为两种:新式类、经典类

  (1)新式类:继承object的类,以及该类的子类。

  (2)经典类:没有继承object的类,以及该类的子类。

 在Python3中默认继承object类,所以Python3中都是新式类;在Python2中要继承object类必须手动继承,所以只有Python中才分新式类和经典类

三、单继承和多继承

class Parent1():
    a = 3

class Parent2():
   a = 3

class Sub1(Parent1):         # 单继承,父类是Parent1,子类是Sub1
    a = 2
    pass


class Sub2(Parent1,Parent2):       # 多继承,父类是Parent1,Parent2,子类是Sub1
    a = 2
    pass

四、查看继承

利用__bases__方法可以查看子类的父类,只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类

class Parent1():
    pass

class Sub1(Parent1):
    pass

print(Sub1.__bases__)

五、继承的作用

继承解决的是类与类之间的代码冗余问题,一定是一个类是另外一个类的子类

六、子类重用父类中的方法(派生)

1、派生:在子类中定义自己的属性,如果与父类的属性重名,那以自己的为准

2、在子类派生出的新方法中重用父类功能的方式一:指名道姓地访问父类中的函数

  Foo.__init__(self,name,age)     不能自动传值,有几个参数就传几个

(1)该方式与继承无关

(2)没有自动传值的效果

 1 class People():
 2     def __init__(self, name, age, sex):
 3         self.name = name
 4         self.age = age
 5         self.sex = sex
 6 
 7 
 8 class Student(People):
 9     def __init__(self, name, age, sex, score=0):
10         # 方式一 调用父类中的__init__函数
11         People.__init__(self, name, age, sex)
12         self.score = score
13 
14     def choose(self):
15         print('%s choosing course' % self)
16 
17 
18 class Teacher(People):
19     def score(self, stu, score):
20         stu.score = score
21 
22 
23 stu = Student('张三', 12, 'male')
24 print(stu.__dict__)      # __dict__可以查看对象的名称空间中的名字
方式一

3、在子类派生出的新方法中重用父类功能的方式二:super(),只能在子类中用

  super().__init__(name,age)    自动传值

(1)在python2中:super(自己的类名,自己的对象)

  在python3:super()    

  调用super()会得到一个特殊的对象,该特殊的对象是专门用来引用父类中的属性的,!!!完全参照mro列表!!!

(2)super()注意点:

  a. 该方式与继承严格依赖于继承的mro列表,类名.mro()      ===>  不管有没有继承关系,super()都是根据mro往后查找
  b. 访问是绑定方法,有自动传值的效果

 1 class People():
 2     def __init__(self, name, age, sex):
 3         self.name = name
 4         self.age = age
 5         self.sex = sex
 6 
 7 
 8 class Student(People):
 9     def __init__(self, name, age, sex, score=0):
10         super().__init__(name,age,sex)
11         self.score = score
12 
13     def choose(self):
14         print('%s choosing course' % self)
15 
16 
17 class Teacher(People):
18     def score(self, stu, score):
19         stu.score = score
20 
21 
22 stu = Student('张三', 12, 'male')
23 print(stu.__dict__)  # 查看对象的名称空间
方式二

七、继承背景下的属性查找

1、单继承背景下的属性查找

单继承背景下属性查找顺序:对象的名称空间------>对象的类的名称空间------->父类的名称空间

 1 class Foo:
 2      x=333
 3      pass
 4 
 5 class Bar(Foo):
 6 #     x=222
 7      pass
 8 
 9 obj=Bar()
10 # obj.x=111
11 print(obj.x)   # 333
单继承背景下的属性查找

2、多继承背景下的属性查找

多继承背景下属性查找的顺序:对象的名称空间------>对象的类的名称空间-------->按照从左往右的顺序一个一个的分支找下去

 1 # 查找顺序是 obj-->A-->B-->E-->C-->F-->I-->D-->H
 2 
 3 #第四层
 4 class I:
 5     # x='I'
 6     pass
 7 
 8 #第三层
 9 
10 class E:
11     # x='E'
12     pass
13 
14 class F(I):
15     # x='F'
16     pass
17 
18 class H:
19     x='H'
20 
21 # 第二层
22 class B(E):
23     # x='B'
24     pass
25 
26 class C(F):
27     # x='C'
28     pass
29 
30 class D(H):
31     # x='D'
32     pass
33 
34 #第一层
35 class A(B,C,D):
36     # x='A'
37     pass
38 
39 obj=A()
40 # obj.x=111
41 print(obj.x)
多继承背景下属性查找

 八、继承顺序

1、在Java和C#中子类只能继承一个父类,而Python中子类可以同时继承多个父类,如A(B,C,D)

2、如果继承关系为非菱形结构,则会按照先找B这一条分支,然后再找C这一条分支,最后找D这一条分支的顺序直到找到我们想要的属性

     下图中的继承关系,继承顺序就是A-->B-->E-->G-->C-->F-->D

 

3、如果继承关系为菱形结构,那么属性的查找方式有两种,分别是:深度优先和广度优先

(1)新式类(继承object的类): 广度优先查找,从左往右一个分支一个分支的查找,在最后一个分支才去查找顶级类

    下图为新式类,继承顺序为:A-->B-->E-->C-->F-->D-->G-->object


(2)经典类(不继承object的类) : 深度优先查找,从左往右一个分支一个分支的查找,在第一个分支就查找顶级类

   下图为经典类,查找顺序为:A-->B-->E-->G-->C-->F-->D

 

posted on 2018-08-20 15:31  凉城旧巷  阅读(137)  评论(0编辑  收藏  举报