python之路day17面向对象进阶
面向对象三大特性之一 ---------- 继承
继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
python中类的继承分为:单继承和多继承
单继承
继承与重用:
子类可以复用父类的方法
# 猫类 : # 属性 : 名字,品种,食物 # 方法 : 叫,抓老鼠,吃,喝 # 狗类 : # 属性 : 名字,品种,食物 # 方法 : 叫,看家,吃,喝 class Animal: def __init__(self,name,kind,food,language): self.name = name self.kind = kind self.food = food self.language = language def yell(self): print('%s叫'%self.language) def eat(self): print('吃%s'%(self.food)) def drink(self): print('喝水') class Cat(Animal): def catch_mouse(self): print('抓老鼠') class Dog(Animal): def look_after_house(self): print('看家')
dog1 = Dog('阿狗','哈士奇','狗粮','嗷嗷')
dog1.look_after_house()
print(dog1.kind)
dog1.eat()
cat1 = Cat('阿猫','橘猫','猫粮','喵喵')
cat1.eat()
cat1.catch_mouse()
print(cat1.__dict__)
print(Cat.__dict__)
print(Animal.__dict__)
继承与派生:
子类在父类的基础上又创建了自己的新的方法和属性
class Animal: def __init__(self,name,kind,food,language): print('in animal') self.name = name self.kind = kind self.food = food self.language = language def yell(self): print('%s叫'%self.name) def eat(self): print('%s吃'%self.name) def drink(self): print('%s喝'%self.name) class Cat(Animal): def __init__(self,name,kind,food,language,eye_color): print('in cat') self.eye_color = eye_color Animal.__init__(self,name,kind,food,language) #继承父类的属性的方法 print(super().__dict__) # super().__init__(name,kind,food,language) #继承父类的属性的方法 def catch_mouse(self): print('抓老鼠') def eat(self): Animal.eat(self)#调用父类的方法 # super().eat() self.weight = 10 class Dog(Animal): def look_after_house(self): print('看家') def eat(self): super().eat() self.drink() c1 = Cat('阿猫','橘猫','猫粮','喵喵','蓝色') print(c1.kind) print(c1.__dict__) c1.catch_mouse() c1.eat() print(c1.__dict__) d1 = Dog('阿狗','哈士奇','狗粮','嗷嗷') d1.eat()
子类中有父类的同名方法 : 只用子类的
还希望用到父类中的方法 : 父类名.方法、super().方法 调用
抽象类
与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
为什么要有抽象类
如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。
比如我们有香蕉的类,有苹果的类,有桃子的类,从这些类抽取相同的内容就是水果这个抽象的类,你吃水果时,要么是吃一个具体的香蕉,要么是吃一个具体的桃子。。。。。。你永远无法吃到一个叫做水果的东西。
从设计角度去看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。
从实现角度来看,抽象类与普通类的不同之处在于:抽象类中有抽象方法,该类不能被实例化,只能被继承,且子类必须实现抽象方法。
from abc import ABCMeta,abstractmethod class Payment(metaclass=ABCMeta): @abstractmethod def pay(self):pass class Alipay(Payment): def pay(self,money): print('使用支付宝支付了%s元'%money) class Wepay(Payment): def pay(self,money): print('使用微信支付了%s元'%money) def pay(obj,money): obj.pay(money) apay = Alipay() apay.pay(100) wpay = Wepay() pay(wpay,200)
规范了继承了父类抽象类的 子类都要实现父类被装饰了方法
应用于多人开发、复杂的需求、后期的扩展 是一种
手段 来帮助我们完成规范
# 抽象类
# 抽象类是一个规范,它基本不会实现什么具体的功能,抽象类是不能被实例化
# 要想写一个抽象类
# from abc import ABCMeta,abstractmethod
# 在这个类创建的时候指定 metaclass = ABCMeta
# 在你希望子类实现的方法上加上一个 @abstractmethod装饰器
# 使用抽象类
# 继承这个类
# 必须实现这个类中被@abstractmethod装饰器装饰的方法
多继承
python / c++有 ;java/c#没有
每个类中有每个类能完成的方法,创建子类的时候只需要挑选和我相符合的父类来继承就能够完成父类的功能了
class Animals: def __init__(self,name): self.name = name class Flyanimal(Animals): def fly(self): print('%s在飞'%self.name) class Walkanimal(Animals): def walk(self): print('%s在走路'%self.name) class Swimanimal(Animals): def swim(self): print('%s在游泳'%self.name) class Tiger(Walkanimal,Swimanimal): def climb(self): print('%s在爬树'%self.name) class Parrot(Flyanimal,Walkanimal): def tak(self): print('%s在说话'%self.name) t1 = Tiger('小老虎') t1.climb() print(Tiger.mro()) t1.swim()
多继承的顺序:
多继承的顺序与新式类和经典类的种类有关
在Python3中所有的类都是新式类,新式类都有一个默认的父类object类,会自动继承object类
在Python2.x中既有新式类又有经典类
class Student:pass # 经典类
class Student(object):pass #新式类
class A: def func(self): print('A') class B(A): pass def func(self): print('B') class C(A): def func(self): print('C') class D(B,C): pass def func(self): print('D') d1 = D() d1.func() print(D.mro()) #[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
mro方法查看查找顺序
以上是PY3版本 新式类
新式类和经典类的区别:
# 新式类中
# 所有的多继承关系寻找方法的顺序 - 遵循广度优先算法
# 继承object
# mro方法
# super : super不是单纯的找父类,而是遵循mro顺序的
# 经典类
# python2.x
# 不主动继承object
# 经典类在找父类中方法的过程中遵循 —— 深度优先
# 不提供mro方法和super