python通过继承、组合、委托组织类
1 python通过继承、组合、委托组织类
# | 概念 | 描述 |
---|---|---|
1 | 继承 | 属性查找X.name |
2 | 多态 | 方法调用X.method,取决于X的类型 |
3 | 封装 | 方法和运算符实现行为 |
通常来说,独特的运算使用独特的方法名称,不要依赖于调用标记。
python组织类结构的方式包括:继承、组合、委托。
1.1 继承:是一个关系
python的继承通过点号运算触发,比如X.name,在实例、类、超类中搜索属性。
# | 概念 | 描述 |
---|---|---|
1 | 超类、基类、父类 | 被继承的类 |
2 | 派生类、子类 | 继承的类 |
3 | 派生 | 父类向子类看 |
4 | 继承 | 子类项父类看 |
子类继承父类,子类和父类为“是一个(is-a)”关系,子类是父类的一种,子类是一个更具体,更全面的父类。
比如:员工是父类,清洁和扫地机器人工是子类,扫地机器人是清洁工,清洁工是一个员工。
示例
class Staff:#员工
def __init__(self,name,salary=0):
self.name=name
self.salary=salary
def payRaise(self,percent):
self.salary=self.salary*(1+percent)
def work(self):#干一些事情
print(self.name,'does stuff')
def __repr__(self):
return '<Staff:name={},salary={}>'.format(self.name,self.salary)
class Cleaner(Staff):#保洁员
def __init__(self,name):
Staff.__init__(self,name,3000)
def work(self):#打扫客房
print(self.name,'cleaning guest rooms')
class Waiter(Staff):#前台服务员
def __init__(self,name):
Staff.__init__(self,name,5000)
def work(self):#接待顾客
print(self.name,'Receiving customers')
class SweepRobot(Cleaner):#扫地机器人
def __init__(self,name):
Staff.__init__(self,name,2000)
def work(self):#打扫大堂
print(self.name,'cleaning the lobby')
if __name__=='__main__':
srb1=SweepRobot('robot1')
print(srb1)
srb1.work()
srb1.payRaise(0.1)
print(srb1);print()
for klass in Staff,Cleaner,Waiter,SweepRobot:
obj = klass(klass.__name__)
obj.work()
'''E:\documents\F盘>python staffs.py
<Staff:name=robot1,salary=2000>
robot1 cleaning the lobby
<Staff:name=robot1,salary=2200.0>
Staff does stuff
Cleaner cleaning the office
Waiter Receiving customers
SweepRobot cleaning the lobby
'''
1.2 组合:有一个关系
python的组合类通过内嵌其他类的对象来实现自己的接口。
组合类有一个或多个内嵌类(组件类)的对象作为自己的属性。
组合类和内嵌类为“有一个(has a)”关系。
比如,酒店类(Hotel)有前台服务员(Waiter)和保洁员(Cleaner)两个类对象作为属性,实现酒店的退房操作。
from staffs import Waiter,Cleaner
class Customer:
def __init__(self,name,roomNo):
self.name=name
self.roomNo=roomNo
def checkOut(self,waiter):#退房
print(self.name,'退房,房号为',self.roomNo)
def backCard(self,waiter):#归还房卡
print(self.name,'归还房卡给',waiter.name)
class Hotel:
def __init__(self):
#Hotel有 Waiter 和 Cleaner 类的对象
self.waiter1 = Waiter('前台1号')
self.cleaner1=Cleaner('保洁员1号')
def checkOut(self,name,roomNo):#退房流程
cust1=Customer(name,roomNo)
cust1.checkOut(self.waiter1)
cust1.backCard(self.waiter1)
self.cleaner1.work()
if __name__ == '__main__':
hot1=Hotel()
hot1.checkOut('顾客1号','168')
'''E:\documents\F盘>python hotel.py
顾客1号 退房,房号为 168
顾客1号 归还房卡给 前台1号
保洁员1号 cleaning guest rooms
'''
1.3 继承组合例子
Processor内嵌reader和writer实例对象,为组合类,并且定义子类继承必须实现的方法converter,为转换器。
streams.py
from abc import ABCMeta,abstractmethod
class Processor:
def __init__(self,reader,writer):#组合类
self.reader=reader#读取器实例
self.writer=writer#写入器实例
def process(self):
while 1:
data=self.reader.readline()
if not data:break
data=self.converter(data)
self.writer.write(data)
@abstractmethod
def converter(self,data):#继承,子类实现转换器
pass
converters.py
from streams import Processor
class Uppercase(Processor):
def converter(self,data):#实现抽象超类的方法
return data.upper()
class HTMLize:
def write(self,line):
print('<UP>{}</UP>'.format(line.rstrip()))
if __name__ == '__main__':
sep='---------------'
import sys
print('查看 tyxt.txt内容:\n{}'.format(open('tyxt.txt').read()))
print(sep)
Uppercase(open('tyxt.txt'),sys.stdout).process()
print()
print(sep)
Uppercase(open('tyxt.txt'),open('tyxtup.txt','w')).process()
print('查看 tyxtup.txt内容:\n{}'.format(open('tyxtup.txt').read()))
print(sep)
Uppercase(open('tyxt.txt'),HTMLize()).process()
'''
E:\documents\F盘>python converters.py
查看 tyxt.txt内容:
tyxt.work
bbs.tyxt.work
---------------
TYXT.WORK
BBS.TYXT.WORK
---------------
查看 tyxtup.txt内容:
TYXT.WORK
BBS.TYXT.WORK
---------------
<UP>TYXT.WORK</UP>
<UP>BBS.TYXT.WORK</UP>
'''
1.4 委托:包装对象
用法
在__init__(self,obj)方法中传入被委托对象(obj),并且赋值给包装类的属性。
在__getattr__(self,attrname)方法,拦截被委托对象的点号运算,返回属性。
示例
class MyWrapper:
def __init__(self,obj):
#传入被委托对象,赋值给包装类的属性
self.wrapped=obj
def __getattr__(self,attrname):
#拦截点号运算
print('trace:',attrname)
#返回被委托对象属性
return getattr(self.wrapped,attrname)
if __name__ == '__main__':
mwL=MyWrapper([1,2,3])
mwL.append('梯阅线条')
print(mwL.wrapped)
'''E:\documents\F盘>python trace.py
trace: append
[1, 2, 3, '梯阅线条']
'''