一,继承和抽象概念
1.抽象:即抽取类似或者比较像的部分。抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类。
抽象分成两个层次:
1)将奥巴马和梅西这俩对象比较像的部分抽取成类;
2)将人,猪,狗这三个类比较像的部分抽取成父类。
2.继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。
二,单继承
1.语法:父类,子类
父类/超类/基类
子类/派生类
2.继承与重用
父类所有的属性和方法都可以被子类使用
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吃%s'%(self.name,self.food)) def drink(self): print('%s喝'%self.name) class Cat(Animal): #子类/派生类 def catch(self): print('%s抓老鼠'%self.name) class Dog(Animal): #子类/派生类 def look_after_house(self): print('%s看家'%self.name) # 继承与重用 - 父类中所有的属性和方法都可以被子类使用了 阿猫 = Cat('阿猫','橘猫','猫粮','喵喵') 阿狗 = Dog('阿狗','二哈','狗粮','汪汪') print(阿猫.name) 阿猫.drink() 阿猫.eat() 阿猫.catch() 阿猫.yell()
3.继承与派生
派生:子类在父类的基础上又新创建了自己需要的方法和属性
1.父类有的子类没有:子类对象直接调用,就会直接执行父类的方法
2.父类有的子类也有:子类对象调用,直接执行子类中的方法,若在子类中使用父类的属性和方法:父类名、super()去调用
class Cat(Animal): #Animal的派生类 def __init__(self,name,kind,food,language,eye_color): self.eye_color = eye_color #派生属性 Animal.__init__(self,name,kind,food,language) #super().__init__(name,kind,food,language) def catch(self): #派生方法 print('%s抓老鼠'%self.name) def eat(self): # 不仅执行了父类中的基础功能,还完成了特殊的功能 Animal.eat(self) #super().eat() self.weight = 10
# 当子类当中有要被调用的方法的时候,子类的对象会直接选择子类中的方法、变量,父类中的方法不会被自动执行
# 如果我们既想要执行子类的方法,也想要执行父类的方法,那么需要在子类的方法中调用父类的方法:
# 父类名.方法名(self,...)
# super().方法名(...)
# 帮助我们在子类中调用父类中的同名方法
# 面向对象特性之继承--面试题
#当self去调用某个方法的时候,不要看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() ################## 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'
4.规范的编程模式:抽象类
抽象类的概念:
1.抽象类是一个规范,它基本不会实现什么具体功能,抽象类是不能被实例化的
2.工作中,有的公司源码有使用抽象类开发的规则,在多人开发,复杂的需求,后期的扩展的场景中,使用抽象类来帮助我们完成规范
# 抽象类语法 # from abc import ABCMeta,abstractmethod # 在这个类创建的时候指定 metaclass = ABCMeta # 在你希望子类实现的方法上加上一个 @abstractmethod装饰器 #抽象类的使用 # 继承这个类 # 必须实现这个类(子类创建同名的方法)中被@abstractmethod装饰器装饰的方法
from abc import ABCMeta,abstractmethod class Payment(metaclass=ABCMeta): # 模板的功能 @abstractmethod # abstractmethod是一个装饰器,放在函数/类的上一行 def pay(self):pass #该抽象类的子类,都必须实现父类的方法,否则报错 class Alipay(Payment): def pay(self,money): print('使用支付宝支付了%d'%money) class wechatpay(Payment): def pay(self,money): print('使用支付宝支付了%d'%money) def pay(obj,money):#构造函数存入对象和参数,自动调用类的方法 obj.pay(money) #TypeError: Can't instantiate abstract class Payment with abstract methods pay #p = Payment() #抽象类实例化会报错 a = Alipay() w = wechatpay() pay(a,100) pay(w,150)
#所有的对象的type都是创造这个对象类 class A:pass obj = A() type(obj) is A #所有没有指定metaclass的类的type都是type #如果指定了metaclass,那么这个类的type就是指定的metaclass的值 #类也是被创造出来的,type是创造类的机制,即元类是创造类的机制
#例:补全func: # - dir方法能够得到当前文件中的所有成员 # - 获取handler中名字叫Base的成员 # - 检查其他成员是否是Base类的子类(不包含Base),如果是则创建对象并添加到objs列表中。 class Base(object):pass class F1(Base):pass class F2(Base):pass class F3(F2):pass class F4(Base):pass class F5(object):pass class F6(F5):pass import sys def func(): name_lst = dir(sys.modules[__name__]) obj_list = [] for name in name_lst: name_addr = getattr(sys.modules[__name__],name) print(type(name_addr)) if type(name_addr) is type and issubclass(name_addr,Base) and name_addr is not Base: obj_list.append(name_addr()) return obj_list ret = func() print(ret)
三,多继承
1.不是所有的语言都支持多继承,例,jave,c#
2.由于python支持多继承,所以python没有接口类
3.其他不支持多继承的语言的接口类,相当于只是继承了一个规范,继承接口类规范的类必须实现接口类的方法
#python的多继承语法 class Parent1:pass class Parent2:pass class Son(Parent1,Parent2):pass print(Son.__bases__) #__bases__查看所有父类,__base__只查看从左到右继承的第一个子类
class Animal: def __init__(self,name): self.name = name class FlyAnimal(Animal): def fly(self): print('%s在飞'%self.name) class WalkAnimal(Animal): def walk(self): print('%s在走路'%self.name) class SwimAnimal(Animal): def swim(self): print('%s在游泳'%self.name) class Tiger(SwimAnimal,WalkAnimal): pass class Swan(SwimAnimal,WalkAnimal,FlyAnimal): pass class Parrot(FlyAnimal,WalkAnimal): def talk(self): print('%s说话了'%self.name) swan = Swan('天鹅') swan.fly() swan.walk()
4.新式类和经典类
#新式类:
#所有的多继承关系寻找方法的顺序:遵循广度优先算法
#继承object
#mro方法
#super:super()不是单纯的找父类,而是遵循mro顺序的
#经典类:
#python2.x
#不主动继承object
#经典类在找父类中方法的过程中,遵循:深度优先
#不提供mro方法和super()
# python 2.7 # 经典类 和 新式类 并存 # class Student:pass # 经典类 # class Student(object):pass # 继承了object的类就是新式类 # 在py3中所有的类都是新式类 # 在py2中既有新式类又有经典类 # 多继承的顺序 在新式类和经典类之间的区别 class A: def func(self): print('A') class B(A): # pass def func(self): print('B') class C(A): # pass def func(self): print('C') class D(B,C): # pass def func(self): print('D') print(D.mro()) d = D() d.func()