Mixin机制
Mixin是混合,糅合(mix in)的意思,这个概念的出现实际上也是为了一些代码的优化
class Vehicle: # 交通工具
def fly(self):
print("I can fly")
class Plane(Vehicle): # 飞机
pass
class Helicopter(Vehicle): # 直升飞机
pass
class Car(Vehicle): # 汽车
pass
'''
'''
汽车虽然是交通工具,但是并不能飞,这种继承方式让汽车已经可以飞了,是不合理的
但是在飞机和直升机中直接写飞的方法又使代码重用了,当类多起来的时候(会飞的交通工具又有很多,不能有一个就写一个飞的方法,这样很麻烦)
为了解决这个问题,Python提供了Mixins机制,简单来说Mixins机制指的是子类混合(mixin)不同类的功能,而这些类采用统一的命名规范(例如Mixin后缀),以此标识这些类只是用来混合功能的
Mixins机制本质是多继承,实际上是一种约定俗成
class Vehicle:
pass
class FlyableMixin:
def fly(self):
print("I can fly")
# 独自封装成一个功能类,用Mixin结尾提醒自己这是个子类混合(功能类),会飞的交通工具直接继承该类就可以了
class Plane(FlyableMixin, Vehicle): # 民航飞机
pass
class Helicopter(FlyableMixin, Vehicle): # 直升飞机
pass
class Car(Vehicle): # 汽车
pass
采用某种规范(如常量命名规范,前面的隐藏属性规范)来解决具体的问题是python惯用的套路
Mixin机制注意事项:
使用Mixin类实现多重继承要非常小心
- 它表示的是一种功能,而不是某个物品,命名时一般以 Mixin, able, ible 为后缀
- 它必须功能单一,如果有多个功能,那就写多个Mixin类,一个类可以继承多个Mixin
- Mixin类只是一个功能,及时没有继承该类也照样可以工作,就是缺少了某个功能
- Mixins是从多个类中重用代码的好方法,但是在继承的层级变多时,代码的可读性就变差了
父类方法重用
让我们继续优化我们的代码
class People:
def __init__(self,name,age):
self.name=name
self.age=age
class Teacher(People):
def __init__(self,name,age,work_period):
self.name=name
self.age=age
self.work_period=work_period
def teach(self):
print('教书育人')
"""
上面的教师类在初始化的时候,因为和父类的初始化有很多重复了的变量所以可以直接使用父类的初始化方法
"""
# 1.直接用类名调用父类的方法
class Teacher(People):
def __init__(self,name,age,work_period):
People.__init__(self,name,age) # 直接使用类名初始化
self.work_period=work_period
# 2.super方法
class Teacher(People):
def __init__(self,name,sex,age,title):
super().__init__(name,age,sex) # 调用的是绑定方法,自动传入self
self.title=title
# 在Python2中super的使用需要完整地写成super(自己的类名,self) ,而在python3中可以简写为super()
# 方式1是跟继承没有关系,而方式2的super()是依赖于继承的,并且即使没有直接继承关系,super()仍然会按照MRO继续往后查找
类的组合
类之间的属性可能又相互引用的关系
class Course: # 课程类
def __init__(self,name,price):
self.name=name
self.price=price
def tell_info(self):
print('<%s %s>' %(self.name,self.price))
class BirthDate:
def __init__(self,year,mon,day):
self.year=year
self.mon=mon
self.day=day
def tell_birth(self):
print('<%s-%s-%s>' %(self.year,self.mon,self.day))
class People:
def __init__(self,name,sex,age):
self.name=name
self.sex=sex
self.age=age
# Teacher类通过继承来重用People的代码
# 通过组合来重用BirthDate类和Course类的代码
class Teacher(People): # 老师类
def __init__(self,name,sex,age,title,year,mon,day):
super().__init__(name,age,sex)
self.birth=BirthDate(year,mon,day) # 直接在类中使用其他类的属性
self.courses=[] # 在实例化后,往该列表中添加Course类对象
def teach(self):
print('%s is teaching' %self.name)
python=Course('python',3000)
linux=Course('linux',5000)
teacher1=Teacher('lilei','female',28,'导师',1990,3,23)
# teacher1有两门课程
teacher1.courses.append(python)
teacher1.courses.append(linux)
# 重用BirthDate类的功能
teacher1.birth.tell_birth()
# 重用Course类的功能
for obj in teacher1.courses:
obj.tell_info()