一、继承
面向对象的语言:c++,c#,java
面对对象的三大特性(继承、多态、封装) 其他语言都有
二、继承和抽象
实例---> 分类 ---> 汇总 逐渐抽象
编程实现:先抽象,后继承
继承的好处:继承能提高代码的重用性,还能规范代码
继承分为子类和父类
父类/超类/基类
子类/派生类
class Animal: # 父类 def __init__(self,name,kind): self.name = name self.kind = kind def sleep(self): print('%s在睡觉'% self.name) class Cat(Animal): # 子类 def catch(self): print('%s抓老鼠'% self.name) cat = Cat('小猫','咖啡猫') print(cat.name) cat.sleep() cat.catch() ------------------ 小猫 小猫在睡觉 小猫抓老鼠 ------------------
继承的语法:
class A:pass
class B(A):pass
class A: # 父类 ... class B(A): # B 继承 A ...
三、单继承
继承与重用
重用:子类可以使用父类中的所有属性和方法,父类中所有的属性和方法都可以被子类使用了
子类可以使用父类中的名字(变量和方法)
class Animal: # 父类 def __init__(self,name,kind): self.name = name self.kind = kind def sleep(self): print('%s在睡觉'% self.name) class Cat(Animal): # 子类 def catch(self): print('%s抓老鼠'% self.name) class Dog(Animal): def walk_the_dog(self): print('溜%s' % self.name) cat = Cat('小猫','咖啡猫') dog = Dog('小狗','导盲犬') cat.sleep() dog.sleep() ----------------- 小猫在睡觉 小狗在睡觉 -----------------
派生
子类在父类的基础上又新创新了自己需要的方法和属性
① 父类有的子类没有--- 子类对象直接调用,就会直接执行父类的方法
② 父类有的子类也有--- 子类对象调用 直接执行子类中的方法
--- 在子类中使用父类的名字:父类名、super()
class Animal: def __init__(self,name,kind): self.name = name self.kind = kind def drink(self): print('%s在喝水'% self.name) class Cat(Animal): # 派生类 def __init__(self,name,kind,eye_color): self.name = name self.kind = kind self.eye_color = eye_color # 派生属性 def catch(self): # 派生方法 print('抓老鼠')
当子类当中有被调用的方法的时候,子类的对象会直接选择子类中的方法或者变量,父类中的方法不会被执行
方法一:子类已存在同名的方法,调用父类的方法
class Animal: def __init__(self,name,kind): self.name = name self.kind = kind def drink(self): print('%s在喝水'% self.name) class Cat(Animal): # 派生类 def __init__(self,name,kind,eye_color): Animal.__init__(self,name,kind) # 调用父类的方法 self.eye_color = eye_color # 派生属性 def catch(self): # 派生方法 print('抓老鼠')
方法二:子类已存在同名的方法,调用父类的方法
class Animal: def __init__(self,name,kind): self.name = name self.kind = kind def drink(self): print('%s在喝水'% self.name) class Cat(Animal): # 派生类 def __init__(self,name,kind,eye_color): # Animal.__init__(self,name,kind) # 调用父类的方法,要加参数self super().__init__(name,kind) # 调用父类的方法,super不需要加self self.eye_color = eye_color # 派生属性 def catch(self): # 派生方法 print('抓老鼠')
子类和父类有同名的方法,如果既要执行子类的方法,也想要执行父类的方法,那么需要在子类的方法中调用父类的方法:
①父类名.方法名(self)
② super().方法名()
super()调用父类的方法,不需要传self,通过父类名调用父类的方法要传self
class Foo: def __init__(self): self.func() def func(self): print('in Foo') class Son(Foo): def func(self): print('in Son') s1 = Son() ''' 结果:in Son '''
self = s1,调用的是Son自己的方法func,所以执行的是子类自身的方法
当self去调用某个方法的时候,不要看self在哪个类里,要看self到底是谁
class Foo: city = 'ShenZhen' def func(self): print(self.city) class Son(Foo): city = 'HONGKONG' s = Son() s.func() ''' 结果 HONGKONG '''
s.func()执行的是父类中的方法,但是调用的属性是Son本身的属性,self就是s,打印的是Son的属性
当self去调用某个方法的时候,不要看self在哪个类里,要看self到底是谁
四、抽象类
抽象类的一个特点是它不能直接被实例化
抽象类的目的就是让别的类继承它并实现特定的抽象方法
抽象基类的一个主要用途是在代码中检查某些类是否为特定类型,实现了特定接口
抽象类的场景:
① 工作中公司有使用抽象类开发的规则
② 看源码,别人的源码使用了抽象类
python使用抽象类的不多
抽象类用来规范代码:
多人开发,复杂的需求、后期的扩展和版本的更新,用新的手段(抽象)来完成规范
抽象类的描述:
抽象类是一个规范,它基本不会实现具体的功能,是由于抽象类不能被实例化
写抽象类:
from abc import ABCMeta,abstractmethod
在这个类创建的时候指定metaclass=ABCMeta
在子类实现的方法加上一个@abstractmethod 装饰器
from abc import ABCMeta,abstractmethod class Payment(metaclass=ABCMeta): @abstractmethod # abstractmethod 是一个装饰器,装饰器放在函数/类的上一行 def pay(self): pass class GooglePay(Payment): def pay(self,money): print('支付了%s元'% money) def pay(obj,money): obj.pay(money) G = GooglePay() a = pay(G,10000) ''' 支付了10000元 '''
装饰器一般放在函数或者类的上一行,表示装饰下一行的函数或者类
使用装饰器:
① 继承这个类
② 必须实现这个类(子类创建同名的方法)被abstractmethod 装饰器 装饰的方法
定义了抽象类必须实行抽象方法,否则会报错
五、多继承
不支持的继承的语言:java,C#
支持多继承的语言:C++,python
多继承的弊端:继承的父类有同名的方法
多继承的定义:python一个子类可以调用多个父类的方法
class Animal: def __init__(self,name): self.name = name class Land(Animal): def walk(self): print('%s 在步行'% self.name) class Sea(Animal): def swim(self): print('%s 在游泳'% self.name) class Air(Animal): def fly(self): print('%s 在飞行'% self.name) class Drogon(Land,Sea,Air): pass class Frog(Sea,Land): pass drogon = Drogon('东海龙') drogon.fly() drogon.swim() drogon.walk() ''' 东海龙 在飞行 东海龙 在游泳 东海龙 在步行 '''
六、接口类
java C# 接口可以被多继承,接口的方法不能有代码。
不允许类的多继承语言,规范继承类必须实现这个方法。
python 中没有接口,抽象类相当于接口
七、新式类和经典类
新式类:python3的版本中,所有的类都是新式类
所有的新式类都有一个默认的父类:object
class Person1:pass # 定义类的写法1 class Person2():pass # 定义类的写法2 class Person3(object):pass # 定义类的写法3 print(Person1.__bases__) print(Person2.__bases__) print(Person3.__bases__) ''' (<class 'object'>,) (<class 'object'>,) (<class 'object'>,) '''
定义类的三种写法:
① 类名:
② 类名():
③ 类名(object):
python2.7版本是经典类和新式类并存
继承了object的类就是新式类:
python3中所有的类都是新式类
python2.7既有新式类又又经典类
不主动继承object都是经典类
新式类和经典类之间多继承顺序的区别:
新式类:
所有的多继承关系寻找方法的顺序是---遵循广度优先算法
① 走过的路不能重复
② 所有的点都要走到
新式类中可以使用类.mro() 查看继承顺序
super() 不是单纯的找父类,而是遵循mro顺序的
经典类:
经典类在找父类中方法的过程中---遵循 深度优先
深度优先:①一条路走到底
② 走过的路不走
class A:pass class B(A):pass class C(A):pass class D(B,C):pass print(D.mro()) ''' [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>] '''
super() 不是单纯的找父类,而是遵循mro顺序的
class A: def func(self): print('A') class B(A): def func(self): super().func() print('B') class C(A): def func(self): super().func() print('C') class D(B,C): def func(self): super().func() print('D') print(D.mro()) D().func() ''' [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>] A C B D '''
新式类与经典类的区别:
新式类:
①所有的多继承关系寻找方法的顺序---遵循广度优先算法
②继承object
③mro方法
④super(): super不是单纯的找父类,而是遵循mro顺序的
经典类:
① python2版本
② 不主动继承object
③ 经典类在找父类中方法的过程中 遵循---深度优先
④ 不提供mro方法和super()
来源:https://www.cnblogs.com/st-st/p/9549379.html