python-16-对象继承
面向对象的三大特征:
封装:根据职责将属性和方法封装到一个抽象的类中
继承:实现代码的重用,相同的代码不需要重复编写
多态:不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度
一、单继承
继承:子类拥有父类的方法和属性
语法:class 类名(父类):
pass
子类继承自父类,可以直接享受父类中已经封装好的方法,不需要再次开发
子类中应该根据职责,封装子类特有的属性和方法
继承的传递性:
C类从B类继承,B类从A类继承
那么C类就具有B类和A类的所有属性和方法
子类拥有父类以及父类的父类 中封装的所有属性和方法
方法的重写:
当父类封装的方法不能满足子类需求时,可以对方法进行重写(Override)
重写有两种:
1、覆盖父类方法(子类方法和父类完全不同)
实现方式,在子类中定义一个和父类同名的方法并实现(只会调用子类方法,不会调用父类的方法)
2、对父类方法进行扩展(子类的方法实现包含父类的方法实现)
在子类中重写父类方法
调用super.父类方法,来调用父类方法执行
代码其他的位置针对子类的需求,缩写子类特有的代码实现
另一种调用父类方法的方式(没有super之前):
父类名.方法(self)不推荐,父类如果变了,方法调用的类名也要改
二、父类的私有属性和私有方法
子类对象不能在自己的方法内部,直接访问父类的私有属性或私有方法;
子类对象可以通过父类的公共方法间接访问到私有属性和私有方法。
class A: def __init__(self): self.num1 = 100 self.__num2 = 200 def __test(self): print("私有方法__test输出属性%d %d" % (self.num1, self.__num2)) def test(self): print("访问私有属性%d" % self.__num2) self.__test() class B(A): def demo(self): # 在子类对象方法中,不能访问父类的私有属性 # print("访问父类的私有属性 %d" % self.__num2) # 也不能调用父类的私有方法 # self.__test() print("父类公有属性%d" % self.num1) self.test() # 创建子类对象 b = B() print(b) b.demo() # 在外界不能直接访问对象的私有属性/调用对象的私有方法 # print(b.__num2) # b.__test()
三、多继承
子类可以拥有多个父类,并且具有所有父类的属性和方法
语法:class 子类名(父类名1,父类名2,……):
pass
1 class A: 2 def test(self): 3 print("A的test方法") 4 5 6 class B: 7 def demo(self): 8 print("B的Demo方法") 9 10 11 class C(A, B): 12 pass 13 14 15 c = C() 16 c.demo() 17 c.test()
注意:
多个父类之间不要存在相同的属性或方法。
1 class A: 2 def test(self): 3 print("A的test方法") 4 5 6 class B: 7 def test(self): 8 print("B的test方法") 9 10 11 class C(A, B): 12 pass 13 14 15 c = C() 16 c.test() # A的test方法
1 class A: 2 def test(self): 3 print("A的test方法") 4 5 6 class B: 7 def test(self): 8 print("B的test方法") 9 10 11 class C(B, A): 12 pass 13 14 15 c = C() 16 c.test() # B的test方法
如果不同的父类之间存在同名的属性或方法,应尽量避免多继承。
四、Python中的MRO --方法搜索顺序
python中针对类有一个提供了一个内置属性 __mro__ 可以查看方法的搜索顺序
MRO是method resolution order ,主要用于多继承时判断方法、属性的调用路径
1 class A: 2 def test(self): 3 print("A的test方法") 4 5 6 class B: 7 def test(self): 8 print("B的test方法") 9 10 11 class C(B, A): 12 pass 13 14 15 c = C() 16 # 确定C类对象调用的顺序 17 print(C.__mro__) 18 c.test()
(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
B的test方法
1 class A: 2 def test(self): 3 print("A的test方法") 4 5 6 class B: 7 def test(self): 8 print("B的test方法") 9 10 11 class C(A, B): 12 pass 13 14 15 c = C() 16 # 确定C类对象调用的顺序 17 print(C.__mro__) 18 c.test()
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
A的test方法
五、新式类和旧式(经典)类
objec是python为所有对象提供的基类,提供有一些内置属性和方法,可以使用dir函数查看
新式类:以object为基类的类,推荐使用
经典类:不以object为基类的类,不推荐使用
新式类和经典类,在多继承时 ,会影响到方法的搜索顺序
为了保证编写的代码同时在python2.X和python3.X运行
今后在定义类时,如果没有父类,建议统一继承自object:
class 类名(object):
pass
在python2.x中