# 继承的引子# 假设咱们如今有一个游戏,游戏中有这些具体的事物(对象 ): 梅西、奥巴马、史努比、史派克、小猪配齐、猪八戒。# 采起面向对象设计的方法,是要对游戏中的具体对象,进行分门别类的抽象,抽取中类似对象的共同特征和行为来,做为一种规范,# 一种模板来,梅西和奥巴马,它们的类似,具备人的特征,所以,咱们把它们归为一类,即人类,就抽象出人类这一律念来了。# 史努力和史派克 具备共同的特征和行为,咱们把它们归为一类,并取名为狗类,完成具体到综合的第一次抽象,而小猪配齐和希猪八戒,# 它们两个具体的事物,又具备共性的东西,所以将它们归为一类,并取名为猪类。# 以上,经过对抽取类似具体事物的共同特征,归为一类,完成了事物的第一层抽象。# 梅西、奥巴马、史努比、史派克、小猪配齐、猪八戒 ===》 人类 、狗类 、 猪类 # 基本的分类# 人类 、狗类 、 猪类 ===》 通过再一次抽象,抽象出 动物类。# 所以面向对象的过程,就是由具体 到 抽象 的过程。从宏观上,概念上 统领类似事物。抽象的层次,越高,可以描述和规范的事物就越多。# # 猫类:# 属性: 名字,品种,食物# 方法: 叫,抓老鼠,吃,喝# 狗类:# 属性: 名字,品种,食物# 方法:叫,看家,吃,喝# 人类:# 属性:名字,品种,食物# 方法:说话,工做,吃,喝# 虽然,咱们从具体的事物,抽象出三个类别,可是咱们发现,这三类之间,还有共同的代码,没有提升代码的重用性。# 因而乎,咱们能够将三个类别的共同代码,再抽取出来,创建一个类别,好比说叫动物类,它让猫类、狗类、人类隶属于这个类,# 也就具备这个类的属性。# 那么用puthon代码如何实现呢?# 定义 一个 Animal() 的父类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 __init__(self,name,kind,food,language,eye_color): # 子类重写父类的方法,并经过super()方法,调用父类的同名方法 self.eye_color = eye_color # 派生属性 super().__init__(name,kind,food,language) # self ,不用传,会自动传 def swim(self): # 派生方法 print("游泳") def look_afte_home(self): print("看家")class Human(Animal): # 派生类 def __init__(self): # 这里子类对父类的方法,进行了重写,即覆盖了父类,此时父类的同名方法,对子类就不可见了。 self.walk_way = "直立行走" def work(self): print("工做")# 在继承关系中,被继承的类,咱们称之为超类/基类/父类, : 好比上面的 Animal类# 继承的类,叫作子类/派生类: 好比上面的 Cat, Dog, Person# 继承与重用:是同一个事物的两方面,类的继承就是了为提升代码的重用性,提升代码的重用性,除了函数,类就是别外一种的实现方式。# 好比说:写了两个类或多个类,它们有共同的代码或逻辑,这时候就能够为它们建立一个父类,把共同的代码或逻辑放到父类里,这时经过继承# 就实现了代码的重用性。# 继承与重用,父类中的全部方法和属性都被子类中使用了。阿猫 = Cat("阿猫","花猫","鱼","喵喵")阿猫.yell()阿猫.eat()阿猫.drink()print(阿猫.name)yellDog = Dog("黄狗","土狗","骨头","汪汪","蓝色")yellDog.eat()yellDog.drink()yellDog.yell()print(yellDog.name)xiaomin = Human() # 由于子类对父类的 __init__方法,进行了重写,除了self之外,没有参数,不须要手动传参。print(xiaomin.walk_way)yellDog.swim()# 总结:当子类当中有要被调用的方法 和 属性的时候,子类的对象会直接选择子类中的方法、变量,父类中的同名方法不会被自动执行。# 若是咱们既想要执行子类中方法,也想要执行父类中的同名方法,那么须要在子类的方法中调用父类的方法:有两种方式:# 父类名.方法名(...)# super().方法名(...)# 面试题:class Foo: def __init__(self): # 初始化对象实例的函数,此函数仅在调用 类名() 时执行一次 self.func() # 对象调用 def func(self): print('in Foo')class Son(Foo): # def func(self): # print("in Son") passs1 = Son() # 建立了一个Son类的对象实例,并赋值给对象引用 s1。过程是,在内存中开辟一个对象空间,根据对象所属的直接类的类#对象指针 找寻 __init__方法执行,子类没有,在父类中寻找,找到将对象传递参数self,执行 __init__函数体,执行self.func()语句,# 对象执行一个方法,先在对象所属直接类中,找到,直接执行,没有找到,再到父类找,因此此处是打印 in Son# class Foo:# Country = 'China'# def func(self):# print(self.Country)## class Son(Foo):# Country = 'English'# def func(self): # 走这个方法# print(self.Country)## s = Son()# s.func()# class Foo:# Country = 'China'# def func(self): # 走这个方法# print(self.Country)## class Son(Foo):# Country = 'English'## s = Son()# s.func() # English# class Foo:# Country = 'China'# def func(self):# print(self.Country)## class Son(Foo):pass## s = Son()# s.func() # 'China'# 结论:始终注意,那个对象调用 ,self就是哪一个对象# 抽象类# 工做中 公司使用抽象类 ,来规范 开发的规则。# 源码 别人使用抽象类from abc import ABCMeta,abstractmethod # 从 abc 这个外部模块中,导入 ABCMeta 类 和 abstracmethod这个用于装饰函数的装饰器class Payment(metaclass=ABCMeta): # 给类的元类,传递一个关键字参数 @abstractmethod def pay(self):pass # 抽象方法,仅有定义,没有方法的实现 @abstractmethod def shouqian(self):pass # 假如,把这两行的注释打开,若是子类不实现这个方法,程序会报错 # a = Alipay() # TypeError: Can't instantiate abstract class Alipay with abstract methods shouqian def abstract(self): print("我继承抽象类")class Alipay(Payment): def pay(self,money): print("使用支付宝支会了%s元" % money) def shouqian(self,money): print("使用收款方式收到%s元" % money)class Wechatpay(Payment): def pay(self,money): print("使用微信支付了%s元" % money) def shouqian(self,money): print("使用收款方式收到%s元" % money)class Applepay(Payment): def pay(self,money): print("使用applepay支付了%s元" % money) def shouqian(self,money): print("使用收款方式收到%s元" % money)# def pay(obj,money):# obj.pay(money)a = Alipay()a.pay(100)a.shouqian(2000)a.abstract() # 抽象类,也能够有普通方法,子类继承wechat = Wechatpay()wechat.pay(260)wechat.shouqian(489)apple = Applepay()apple.pay(159)apple.shouqian(6000)# 以上多个子类,继承同一个抽象类,子类必须去实现抽象类中用@abstractmethod装饰器装饰的方法,不然会报错。# 实现了不一样的对象,调用相同的方法# 在上面的基础上,咱们来定义 一个 统一的函数,也能够叫接口def 付钱(obj,money): obj.pay(money)# 这样,func()就是一个统一的支付接口付钱(wechat,1600)付钱(a,3500)def 收钱(obj,money): obj.shouqian(money)收钱(a,10000)收钱(apple,30000)# p = Payment() # 抽象类 , 不能实例化 TypeError: Can't instantiate abstract class Payment with abstract methods pay, shouqian# 总结: 抽象类 是一种 规范# 多人开发、复杂的需求、后期的扩展# 手段,来帮助咱们完成规范。# 抽象类 如何建立# 抽象类是一个规范,它基本上不会实现什么具体的功能,抽象类是不能被实例化的。# 要想写一个抽象类的步骤:# from abc import ABCMeta,abstractmethod# 在建立这个类的时候,指定 metaclass = ABCMeta# 在你但愿子类实现的方法上加一个 @abstractmethond 装饰器# 使用抽象类:# 继承这个类# 必须实现这个类中被 @abstractmehond 装饰器装饰的方法