面向对象三大特性:封装、继承、多态
封装:根据职责将属性和方法封装在抽象类中
继承:实现代码的重用
多态:不同对象调用相同方法,产生不同结果
1、单继承
继承:子类拥有父类的方法和属性
# 继承的概念 子类拥有父类所有的方法和属性,实现代码的重用,简化代码的结构
# 实现单继承
class Animal:
"""父类"""
def __init__(self):
"""初始化方法"""
self.name = "动物"
self.age = 2
def eat(self):
"""吃方法"""
print("%s都有吃方法" % self.name)
class Cat(Animal): # 单继承
"""猫类"""
def catch(self):
"""抓老鼠方法"""
print("小猫抓老鼠")
# 使用父类模板创建对象
animal = Animal()
print(animal.name)
print(animal.age)
animal.eat()
# animal.catch() # 父类对象无法调用子类的方法
tom = Cat()
print(tom.name)
print(tom.age)
tom.catch() # 子类继承了父类,子类可以调用父类的属性和方法,还可以调用子类自己的方法
1.1 方法的重写
子类继承父类的所有方法和属性,当父类的方法无法满足子类需求,可以对方法进行重写
重写方法:
1.覆盖
在开发中,父类的方法和子类的方法完全不同,在子类中重新编写父类的方法实现
2.扩展
子类的方式实现包含父类的方法实现
1.在子类中重写父类的方法
2.在需要的位置使用super().父类方法来调用父类方法执行
3.代码其他位置针对子类代码需求,编写子类特有代码实现
super是python中一个特殊类,super()就是super类创建出来的对象。
调用父类的另一种方式:父类名.方法(self)# 不推荐使用,一旦父类名变更,所有方法调用位置父类名同样需要变更。
2、多继承
子类可以拥有多个父类,同时拥有多个父类的方法和属性。
2.1多继承的注意事项
如果不同的父类拥有相同的方法名,子类在调用时候会调用哪一个父类的方法?
注意:在开发的时候要尽量避免这种情况,如果父类有相同的方法名或属性名,尽量避免十四用多继承。
python中的mro--方法搜索顺序:
python中针对类提供一个__mro__属性,可以查看方法的搜索顺序
在搜索方法时,是按照__mro__输出结果,从左到右顺序查找,如果找到,就执行,不再搜索,没有找到,就从下一个类中搜索,直到找到最后一个类,没有找到,报错。
2.2 新式类和经典类
object类是python为所有对象提供的基类,提供一些内置属性和方法,可以使用dir方法查看。
新式类:以object类为基类的类,推荐使用
经典类:不以object为基类的类,不推荐使用
在python3.x中,如果没有指定父类,会将object作为基类--3.x中所有的类都是新式类
在python2.x中,如果没有指定父类,不会将object作为基类
新式类和经典类会影响方法的搜索顺序
注意:为了保重代码在3.x和2.x中都能运行,没有父类,统一继承自object
# 多继承:子类可以拥有多个父类,并且具有su哦有父类的属性和方法
class Horse:
"""马类"""
def __init__(self):
self.name = "马"
def run(self):
print("马跑得快")
def walk(self):
print("马累了也走,但是走不远")
class Donkey:
"""驴类"""
def __init__(self):
self.name = "驴"
def walk(self):
print("驴走得远")
class Mule(Horse, Donkey):
"""骡子类"""
pass
# 使用骡子类来创建对象
mu = Mule() # 骡子类继承了马类和驴类,骡子类创建的对象继承了父类的所有属性和方法,不包含私有属性和方法
mu.run()
# 当父类定义了相同的属性和方法,值继承第一个
mu.walk()
print(mu.name)
# 子类调用的属性和方法顺序(先从在自己类中寻找,再从上往下寻找)
print(Mule.__mro__)
# 新式类和旧式类 新式类:以object为基类的类,推荐使用 经典类:不以object为基类的类,不推荐使用
# python3.x中定义类时,如果没有指定父类,以object为父类
# python2.x中定义类时,如果没有指定父类,不以object为父类
# object类