0x01:程序里的继承

继承是面向对象软件设计中的一个概念,与多态、封装共为面向对象的三个基本特征。继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。

image.png

  • 在程序中,继承描述的是多个类之间的所属关系。
  • 如果一个类A里面的属性和方法可以复用,则可以通过继承的方式,传递到类B里。
  • 那么类A就是基类,也叫做父类;类B就是派生类,也叫做子类。
  1. class Animal(object):
  2. def __init__(self, name, age):
  3. self.name = name
  4. self.age = age
  5. def sleep(self):
  6. print(self.name + '正在睡觉')
  7. class Dog(Animal):
  8. def bark(self):
  9. print(self.name + '正在叫')
  10. class Student(Animal):
  11. def study(self):
  12. print(self.name + '正在好好学习')
  13. # Dog() 调用 __new__ 方法,再调用 __init__ 方法
  14. # Dog 里没有 __new__ 方法,会查看父类是否重写了 __new__ 方法
  15. # 父类里也没有重写 __new__ 方法,查找父类的父类,找到了 object
  16. # 调用 __init__ 方法,Dog类没有实现,会自动找 Animal 父类
  17. d1 = Dog('大黄', 3)
  18. print(d1.name) # 父类里定义的属性,子类可以直接使用
  19. d1.sleep() # 父类的方法子类实例对象可以直接调用
  20. d1.bark()
  21. s1 = Student('小明', 18)
  22. s1.sleep()
  23. s1.study()
  24. # s1.bark()

0x02:继承的注意使用

在Python中,继承可以分为单继承、多继承和多层继承。

(1)单继承:子类只继承一个父类

继承概念:子类用于父类的所有的方法和属性。

image.png

  1. 继承语法:
  2. class 类名(父类名):
  3. pass
  • 子类继承自父类,可以享受父类中已经封装好的方法,不需要再次定义
  • 子类中应该根据职责,封装子类特有的属性和方法。

继承的传递性

Dog类继承自Animal, XiaoTianQuan又继承自Dog类,那么XiaoTianQuan类就具有了Animal类里的所有属性和方法。
子类拥有父类以及父类的父类中封装的所有属性和方法。

(2)多继承

子类可以拥有多个父类,并且具有所有父类的属性和方法。
image.png

  1. 语法格式:
  2. class 子类名(父类名1,父类名2...)
  3. pass

多继承的使用注意事项

Python中的MRO

  • Python中针对类提供了一个内置属性mro可以用来查看方法的搜索顺序。
  • MRO 是method resolution order的简称,主要用于在多继承时判断方法属性的调用顺序。
  1. class A(object):
  2. pass
  3. class B(object):
  4. def foo(self):
  5. print('我是B类里的foo方法')
  6. class C(A):
  7. def foo(self):
  8. print('我是C类里的foo方法')
  9. class D(B):
  10. pass
  11. class E(object):
  12. pass
  13. class X(C, D, E):
  14. pass
  15. x = X()
  16. x.foo()
  17. print(X.__mro__)
  18. 我是C类里的foo方法
  19. (<class '__main__.X'>, <class '__main__.C'>, <class '__main__.A'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class 'object'>)
  • 在调用方法时,按照mro的输出结果从左至右的顺序查找。
  • 如果再当前类中找到方法,就直接执行,不再向下搜索。
  • 如果没有找到,就顺序查找下一个类中是否有对应的方法,如果找到,就直接执行,不再继续向下搜索。
  • 如果找到了最后一个类,依然没有找到方法,程序就会报错。

(3)私有属性的继承特点

私有属性和方法,子类不会继承

  1. class Animal(object):
  2. def __init__(self, name, age):
  3. self.name = name
  4. self.age = age
  5. self.__money = 1000
  6. def eat(self):
  7. print(self.name + '正在吃东西')
  8. def __test(self):
  9. print('我是Animal类里的test方法')
  10. class Person(Animal):
  11. def __demo(self):
  12. print('我是Person里的私有方法')
  13. p = Person('张三', 18)
  14. print(p.name)
  15. p.eat()
  16. p._Person__demo() # 自己类里定义的私有方法 对象名._类名__私有方法名()
  17. p._Animal__test() # 可以通过 对象名._父类名__私有方法调用()
  18. # 私有属性和方法,子类不会继承
  19. # p._Person__test() # 父类的私有方法,子类没有继承
  20. # print(p._Person__money)
  21. print(p._Animal__money)

(4)新式类和旧式(经典)类

object是Python中所有对象的基类,提供了一些内置的属性和方法,可以时候用dir函数查看。

  • 新式类:以object为基类的类,推荐使用
  • 经典类:不以object为基类的类,不推荐使用

  • 在 Python3.x 以后定义类时,如果没有指定父类,这个类会默认继承自 object,所以,python3.x版本定义的类都是新式类。

  • 在Python2.x中定义类时,如果没有指定父类,则不会继承自object.

为了保证代码在Python2.x和Python3.x中都能够运行,在定义类时,如果一个类没有父类,建议统一继承自’object’。

  1. class 类名(object):
  2. pass