一,继承和抽象概念
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()