面向对象,继承

今日类容

1.什么是继承

2.继承的基本语法

3.继承与抽象

4.属性的查找顺序

5.派生与覆盖

6.如何实现一个可以限制元素的类型的列表

7.子类访问父类的内容

8.组合

9.菱形继承

一 什么是继承

1.什么是继承:

    继承是一种关系,描述俩个对象之间,什么是什么的关系,

    列如麦兜,佩奇,都是猪, 在程序中,继承描述的是类和类之间的关系

    列如a继承了b,a就能直接使用b已经存在的方法和属性,a称之为子类,b称之为父类,也称之为基类

2.什么时候用继承:
    假如已经有几个类,而类与类之间有共同的变量属性和函数属性,那就可以把这几个变量属性和函数属性提取出来作为基类的属性。而特殊的变量属性和函数属性,则在本类中定义,这样只需要继承这个基类,就可以访问基类的变量属性和函数属性。可以提高代码的可扩展性。

 

二 继承的基本语法

class Base:
    desc = "这是一个基类"

    def show_info(self):
        print(self.desc)

    def make_money(self):
        print("一天赚一个亿...")

#指定父类位Base
class SubClass(Base):
    pass

obj = SubClass()
#即使类中什么都没有也可以使用父类中已有的内容
obj.make_money()
print(obj.desc)

 

三 继承与抽象

1.什么是抽象:

   不具体,不清晰,看不懂,不是确切存在的,

   将多个子类中相同的部分,进行抽取,形成一个新的类,这个过程也称之为抽象的过程

 

2.如何正确的使用继承:
  1.先抽象在继承

  2.继承一个已经现存的类,扩展或是修改原始的功能

案例 :

继承的错误示范:

 1 class Teacher:
 2     school = 'oldboy'
 3     def __init__(self,name,age):
 4         self.name = name
 5         self.age = age
 6 
 7     def say_hi(self):
 8         print('hello i am %s'%self.name)
 9 
10     def teach(self):
11         print('正在教书')
12 
13 class Student(Teacher):
14     pass
15 
16 print(Student.school)
17 print(Student.say_hi)
18 print(Teacher.say_hi)
19 
20 stu = Student('zy',19)
21 stu.say_hi()
22 stu.teach()
23 '''
24 上述案例中打招呼的技能老师和学生都有,但是老师教书的技能,学生不应该继承过来,这是不合理的
25 '''
View Code

 

继承的正确示范:

 1 # 继承的改良版: 需要先抽象在继承
 2 
 3 class OldBoyPerson:
 4     school = 'oldboy'
 5     def __init__(self,name,age):
 6         self.name = name
 7         self.age = age
 8 
 9     def say_hi(self):
10         print('hello i am %s '% self.name)
11 
12 class Teacher(OldBoyPerson):
13     def teach(self):
14         print('正在教书')
15 
16 class Student(OldBoyPerson):
17     pass
18 
19 # t = Teacher('zy',19)
20 # t.say_hi()
21 # t.teach()
22 
23 s = Student('sm',19)
24 s.say_hi()
25 '''
26 总结:先抽象 定义一个把老师类和学生类都放在定义的一个人类之中,在人类中设置一个人类都会的打招呼技能
27 然后老师和学生在继承那个他们都会的一个技能就可以了
View Code

 

四 属性的查找顺序

查找顺序:对象自己的 - > 所在类中 -> 找父类 - >父类的父类 ->Object

案例:

class A:
    name = 'scot'


class B(A):
    name = 'rose'
    pass
b = B()
b.name = 'jack'

print(b.name)
print(b.__str__())

# 查找顺序
# 对象自己 - > 所在的类 -> 所在类的父类 -> 父类的父类  -> object

 

五 派生与覆盖

1.什么是派生:  

   当一个子类中出现了与父类中不同的内容时,这个子类就称之为派生类

   通常子类都会写一些新的代码,不可能和父类完全一样 , 既通常都是派生类,

   所以派生类指的就是子类

  

2.什么是覆盖:
   也称之为重写 overrides

   当子类出现了与父类名称完全一致的属性或是方法

 

案例:派生

 1 派生:
 2 当一个类继承自另一个类,并且这个子类,并且这个子类拥有与父类不同的类容
 3 '''
 4 
 5 class A:
 6     def show_info(self):
 7         print('hello world')
 8 
 9 class B(A):
10     pass
View Code

 

案例:覆盖

 1 覆盖(重写)
 2 子类中出现了与父类相同的属性或者方法,就会覆盖掉父类的方法和属性
 3 '''
 4 class A:
 5     text = '123'
 6     def sjow_info(self):
 7         print('hello world')
 8 
 9 
10 class B(A):
11     text = '321'
12     def show_info(self):
13         print('hello nishishabi')
14 
15     pass
16 
17 b = B()
18 b.show_info()
19 print(b.text)
View Code

 

六 如何实现一个可以限制元素的类型的列表

 1 '''
 2 继承已有的类来扩展新功能:
 3 
 4 实现一个存储类,在提供基本的存取功能之外,还要可以限制存储元素的类型
 5 '''
 6 
 7 class MyList(list):
 8     def __init__(self,element_cls):
 9         # 当你覆盖init方法时,不要忘记调用super().init 函数让父类完成原有的初始化操作
10         super().__init__()
11         self.element_cls = element_cls
12 
13 
14     def append(self, object):
15         if object.__class__ == self.element_cls:
16             super().append(object)
17         else:
18             print('你只能存储%s类型'%self.element_cls.__name__)#
19 
20 
21 # 可以指定存储的类型
22 li = MyList(str)
23 li.append(20)
24 li.append('123')
25 print(li)
View Code

 

七 子类访问父类的内容

1.语法  

  方式1:
  super(当前类名称,self).你要调的父类的属性或方法
  方式2:
  super().你要调的父类的属性或方法
  方式3:
  类名称.你要调的父类的属性或方法(self)
  #方式3与继承无关

  

注意:

  当你继承一个现有的类,并且你覆盖了父类的init方法时,必须在初始化方法的

  第一行调用父类的初始化方法,并传入父类所需的参数

案例:

 1 class Person:
 2     text = '321'
 3     def __init__(self,name,age,gender):
 4         self.name = name
 5         self.age = age
 6         self.gender = gender
 7 
 8     def sleep(self):
 9         print('人类已经睡着了,午睡,躺着睡')
10 
11 
12     def say_hi(self):
13         print(f'my name is {self.name} my age is {self.age}  my gender is {self.gender}',end=" ")
14 
15 class Student(Person):
16     text = '123'
17     def __init__(self,name,age,gender,number):
18 # 因为父类已经存在了一个方法可以完成这三个参数的初始化,
19 # 所以就可以吧还缺的一个参数 补上就好了,其他的直接调用父类的进行初始化
20 #         Person.__init__(self,name,age,gender)# 指名道姓的调用
21 
22         # 方法二,py2 不支持
23         super().__init__(name,age,gender)
24         self.number = number
25 
26         # py 中的写法
27         # super(Student, self).__init__(name,age,gender)
28         # self.number = number
29 
30     # 访问父类的属性
31     def show_text(self):
32         print(self.text)
33         print(super().text)
34 
35     def say_hi(self):
36         super().say_hi()
37         print(f'my num is {self.number}')
38 
39 stu = Student('zy',19,'man','0001')
40 
41 stu.say_hi()
42 
43 stu.show_text()
View Code

 

八 什么是组合

1. 什么是组合:

  指的是 一个类把另一个类的对象作为自己的属性 就称之为组合
  无处不在
  当你定义一个类 并且这个类拥有某种类型的属性时 就称之为组合
  都是用用来重用代码的方式:
  组合描述的是 什么拥有什么的关系 学生 有 书 学生有手机
  基础描述的是 什么是什么的关系 麦兜是猪 猪猪侠也是猪

2.组合的目的:

  也是为了重用现有代码

  什么时候使用继承:分析两个类的关系,到底是不是:什么是什么的关系

  什么时候使用组合:如果两个类之间 没有太大的关系,完全不属于同类

  另外组合相比继承,耦合度更低了


案例:

 1 class Phone:
 2     def __init__(self,price,kind,color):
 3         self.price = price
 4         self.kind = kind
 5         self.color = color
 6 
 7     def call(self):
 8         print("正在呼叫XXXX;")
 9 
10     def send_message(self):
11         print("正在发送短信....")
12 
13 
14 class Student:
15     def __init__(self,name,gender,phone):
16         self.name = name
17         self.gender = gender
18         self.phone = phone
19 
20     def show_info(self):
21         print("name:%s gender:%s" % (self.name,self.gender))
22 
23 phone = Phone(1000,"apple","red")
24 
25 stu1 = Student("rose","male",phone)
26 stu1.phone.call()
View Code

 

九 菱形继承

补充:多继承的时候,如果多个父类出现了同名的属性和函数,
需要用mro列表啦查看真正的继承关系,
总结:super在访问父类属性时,是按照mro列表一层层网上找

什么是菱形继承:
补充:新式类与经典类

python3中任何类都是直接或间接继承了Object

新式类,任何显式或隐式地继承自object的类就称之为新式类, python3中全都是新式类

经典类,既不是Object的子类 ,仅在python2中出现

 

当出现了菱形继承时,新式类,先深度,当遇到了共同父类时就广度

新式类,就是深度优先

案例:
 1 class A:
 2     def test(self):
 3         print('from A')
 4         super().test()
 5 
 6 
 7 class B:
 8     def test(self):
 9         print('from B')
10     pass
11 
12 
13 class C(A,B):
14     pass
15 
16 c = C()
17 c.test()
18 print(C.mro())
19 
20 
21 class A:
22     a = 1
23     pass
24 
25 class B(A):
26     a = 2
27     pass
28 
29 class C(A):
30     a =3
31     pass
32 
33 class D(A):
34     a = 4
35     pass
36 
37 class E(B,C,D):
38     a = 5
39     pass
40 
41 e = E()
42 print(e.a)
43 print( E.mro())
View Code

  

    

  

 

posted @ 2019-07-25 20:47  ZHANGYUZY  阅读(154)  评论(0编辑  收藏  举报