[复习]面向对象之继承

面向对象之继承

一.概念

 如果有两个或两个以上的类具有相同的属性和方法,我们可以抽取出来,把抽取出来的部分作为各个类的公共部分,我们称抽取出的这部分为基类[Base Class]或者父类[Father Class]、超类[Super Class].

  举例:[我直接以多继承举例]

  第一种情况,父类中没有构造函数

 

 1 class Father(object):
 2     def eat(self):
 3         print('father is eating')
 4 
 5 
 6 class Mother(object):
 7     def play(self):
 8         print('mother is playing')
 9 
10 
11 class Children(Father, Mother):
12     pass
13 
14 
15 c = Children()
16 c.eat()
17 c.play()

 

  运行结果

1 father is eating
2 mother is playing

 

 

  第二种情况,父类中有构造函数
 1 class Father(object):
 2     def __init__(self, money):      # 构造函数
 3         self.money = money      # 实例属性
 4 
 5     def get(self):
 6         print(f'father had got {self.money}$')
 7 
 8 
 9 class Mother(object):
10     def __init__(self, clothes):        # 构造函数
11         self.clothes = clothes      # 实例属性
12 
13     def shop(self):
14         print(f'mother has go shopping to buy {self.clothes}')
15 
16 
17 # 如果子类想要用父类中的实例属性,则需要继承父类的构造函数才能使用,否则会报错
18 # 如果父类中含有多个重名的函数,那么子类只会调用父类列表第一个重名的函数
19 class Children(Father, Mother):
20     def __init__(self, money, clothes):
21         Father.__init__(self, money)
22         Mother.__init__(self, clothes)
23 
24 
25 c = Children(100,'李宁')
26 c.get()
27 c.shop()

 

  运行结果

1 father had got 100$
2 mother has go shopping to buy 李宁
  第三种情况,父类中有构造函数,子类中没有
 1 class Father(object):
 2     def __init__(self, money):      # 构造函数
 3         self.money = money      # 实例属性
 4 
 5     def get(self):
 6         print(f'father had got {self.money}$')
 7 
 8 
 9 class Mother(object):
10     def __init__(self, clothes):        # 构造函数
11         self.clothes = clothes      # 实例属性
12 
13     def shop(self):
14         print(f'mother has go shopping to buy {self.clothes}')
15 
16 
17 class Children(Father, Mother):
18    
19     pass
20 
21 
22 c = Children(100)
23 c.get()
24 c.shop()

   运行结果则是 只能调用Father中的函数,而Mother中的无法调用

 

总结:

1.在多继承中,如果父类中有构造函数,子类没有,而子类需要使用父类中的实例属性或函数,那么子类只会调用第一个父类的函数;如果想要子类使用所有父类的实例属性或函数,那么同样需要继承父类中的构造函数,但是如果使用super()都只能调用父类列表中第一个父类中的构造函数,所以只能使用上述例子的第二种继承方法

2.如果在父类中都没有构造函数,那么子类可以直接调用

 

二、函数的重写[重点掌握]

   函数的重写[override],使用的前提是在继承的情况下;

   如果在子类中重新实现了父类中的函数,那么这个过程叫做函数的重写。

  举例:

 

 1 # 1.第一种情况:普通函数的重写
 2 class Animals(object):
 3     def walk(self):
 4         print('正在跑')
 5 
 6 
 7 class Dog(Animals):
 8     pass
 9 
10 
11 class Cat(Animals):
12     pass
13 
14 
15 class Bird(Animals):
16     def walk(self):
17         print('鸟只会飞')
18 
19 
20 animal = Bird()
21 animal.walk()
22 
23 animal2 = Dog()
24 animal2.walk()
25 
26 # 2.第二种情况,系统函数的重写,拿object举例,因为所有类的基类都是object
27 class Person(object):
28     def __init__(self, name, age):
29         self.name = name
30         self.age = age
31 
32     def __str__(self):
33         return f'姓名:{self.name},年龄:{self.age}'
34 
35     def __repr__(self):
36         return f'姓名:{self.name},年龄:{self.age}'
37 
38     __repr__ == __str__
39 
40 
41 p = Person('小刚',19)
42 print(p)

 

  运行结果:

1 鸟只会飞
2 正在跑
3 姓名:小刚,年龄:19

 

 

总结:

1.什么时候用函数的重写

  如果一个父类中有多个子类,父类中的函数能够满足大部分子类的使用,只有少部分函数无法使用时,我们可以用函数的重写;

2.什么时候需要重写__str__

  如果希望打印出的信息是当前对象的属性,那么需要在子类中重写__str__,因为它返回的是一个字符串,所以建议将字符串格式化之后返回,如例子中的。

3.什么时候需要重写__repr__

  如果打印出的信息对象元素是存在于列表等可迭代对象中,它会直接返回可迭代对象,也就是返回默认的地址形式,但是我们需要的是列表中的属性信息,那么我们就需要重写__repr__

4.只要有系统函数的重写都需要加上 __repr__ == __str__

 

 

三、函数的重写和函数的重载有什么区别

  【面试题】简述函数重写和函数重载的区别
    函数重写:override,在继承的前提下,如果子类中重新实现了父类中的函数
    函数重载[运算符重载]:overload,对于自定义的类,通过该类创建的对象,如果不支持某些运算,如:+ - * / > < >= <= == !=等,则可以在该类中实现这些运算符对应的函数

 

    

 1 class Person(object):
 2     def __init__(self, age):
 3         self.age = age
 4     
 5     def __add__(self, other):        # 函数重载
 6        # self和other表示参与运算的两个对象
 7        # 结合实际情况,两个对象无法相加,可以对两个对象的属性进行加法运算
 8         return Person(self.age+other.age)    
 9     
10     def __str__(self):    
11         return str(self.age)
12     __repr__ == __str__
13 
14 
15 p1 = Person(10)
16 p2 = Person(5)
17 
18 print(p1+p2)
19 print(p1.__add__(p2))

 

posted @ 2023-02-02 18:24  学python的菜鸟  阅读(15)  评论(0编辑  收藏  举报