python基础_类+继承+组合
面向过程程序设计:流水线型,对解决一个问题,流水线可以使处理过程简单化,但是可扩展性差,牵一发而动全身。
面向对象程序设计:核心是对象,对象是特征与动作的结合体,在程序中的体现就是类是对象,与之相对的就是数据属性和函数属性,可扩展性好。
类的内置属性:
__init__方法:类的初始化函数 强调: 1、该方法内可以有任意的python代码 2、一定不能有返回值
python为类内置的特殊属性 类名.__name__# 类的名字 类名.__doc__# 类的文档字符串 类名.__base__# 类的第一个父类 类名.__bases__# 类所有父类构成的元组 类名.__dict__# 类的字典属性 类名.__module__# 类定义所在的模块 类名.__class__# 实例对应的类
类的两种属性:
1.类的数据属性是所有对象共享的,id都一样
2.类的函数对象是绑定给对象用的,内存地址都不一样
#id是python的实现机制,并不能真实反应内存地址,如果有内存地址,还是以内存地址为准
继承
继承是创建一个新类的方法,创建的新类可以继承一个类或多个类的。父类又称基类或超类,子类又称派生类。
子类会遗传父类的属性(代码重用)
子类.__base__只查看从左到右继承的第一个父类 子类.__bases__则是查看所有继承的父类 class ParentClass1: #定义父类 pass class ParentClass2: #定义父类 pass class SubClass1(ParentClass1): pass class SubClass2(ParentClass1,ParentClass2): pass >>> SubClass1.__bases__ (<class '__main__.ParentClass1'>,) >>> SubClass2.__bases__ (<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)
派生:
子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。
在子类中,新建的重名的函数属性,在编辑函数内功能的时候,有可能需要重用父类中重名的那个函数功能,应该是用调用普通函数的方式,即:类名.func(),此时就与调用普通函数无异了,因此即便是self参数也要为其传值。
class Hero: def __init__(self,nickname,aggressivity,life_value): self.nickname=nickname self.aggressivity=aggressivity self.life_value=life_value def move_forward(self): print('%s move forward' %self.nickname) def move_backward(self): print('%s move backward' %self.nickname) def move_left(self): print('%s move forward' %self.nickname) def move_right(self): print('%s move forward' %self.nickname) def attack(self,enemy): enemy.life_value-=self.aggressivity class Riven(Hero): camp='Noxus' def __init__(self,nickname,aggressivity,life_value,skin): Hero.__init__(self,nickname,aggressivity,life_value) #调用父类功能 self.skin=skin #新属性 def attack(self,enemy): #在自己这里定义新的attack,不再使用父类的attack,且不会影响父类 Hero.attack(self,enemy) #调用功能 print('from riven') def fly(self): #在自己这里定义新的 print('%s is flying' %self.nickname)
组合:
组合是指在一个类中以另一个类的对象作为数据属性,称为类的组合。
代码重用除继承外,还有一种就是组合。
>>> class Equip: #武器装备类 ... def fire(self): ... print('release Fire skill') ... >>> class Riven: #英雄Riven的类,一个英雄需要有装备,因而需要组合Equip类 ... camp='Noxus' ... def __init__(self,nickname): ... self.nickname=nickname ... self.equip=Equip() #用Equip类产生一个装备,赋值给实例的equip属性 ... >>> r1=Riven('锐雯雯') >>> r1.equip.fire() #可以使用组合的类产生的对象所持有的方法 release Fire skill
当类之间有明显的不同时,且较小类是较大类的组件时,用组合比较好
接口与归一化:
接口作用:自己提供给使用者来调用自己的功能的方式
归一化:所有对象的调用方式相同
接口提取了一群类共同的函数,可以把接口当做一个函数的集合。然后让子类去实现接口中的函数。这么做的意义在于归一化,什么叫归一化,就是只要是基于同一个接口实现的类,那么所有的这些类产生的对象在使用时,从用法上来说都一样。
抽象类:
抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
抽象类与普通类的不同之处在于:抽象类中只能有抽象方法(没有实现功能),该类不能被实例化,只能被继承,且子类必须实现抽象方法。
#一切皆文件 import abc #利用abc模块实现抽象类 class All_file(metaclass=abc.ABCMeta): all_type='file' @abc.abstractmethod #定义抽象方法,无需实现功能 def read(self): '子类必须定义读功能' pass @abc.abstractmethod #定义抽象方法,无需实现功能 def write(self): '子类必须定义写功能' pass # class Txt(All_file): # pass # # t1=Txt() #报错,子类没有定义抽象方法 class Txt(All_file): #子类继承抽象类,但是必须定义read和write方法 def read(self): print('文本数据的读取方法') def write(self): print('文本数据的读取方法') class Sata(All_file): #子类继承抽象类,但是必须定义read和write方法 def read(self): print('硬盘数据的读取方法') def write(self): print('硬盘数据的读取方法') class Process(All_file): #子类继承抽象类,但是必须定义read和write方法 def read(self): print('进程数据的读取方法') def write(self): print('进程数据的读取方法') wenbenwenjian=Txt() yingpanwenjian=Sata() jinchengwenjian=Process() #这样大家都是被归一化了,也就是一切皆文件的思想 wenbenwenjian.read() yingpanwenjian.write() jinchengwenjian.read() print(wenbenwenjian.all_type) print(yingpanwenjian.all_type) print(jinchengwenjian.all_type)
继承顺序:
查看继承顺序 子类.mro() #等同于子类.__mro__
查找父类(MRO列表)的三条准则:
1.子类先于父类被检查
2.多个父类会根据他们在列表中的顺序被检查
3.如果下一个类存在两个合法选择,选第一个父类
子类调用父类方法:
方法一:父类名.父类方法
#_*_coding:utf-8_*_ __author__ = 'Linhaifeng' class Vehicle: #定义交通工具类 Country='China' def __init__(self,name,speed,load,power): self.name=name self.speed=speed self.load=load self.power=power def run(self): print('开动啦...') class Subway(Vehicle): #地铁 def __init__(self,name,speed,load,power,line): Vehicle.__init__(self,name,speed,load,power) self.line=line def run(self): print('地铁%s号线欢迎您' %self.line) Vehicle.run(self)
方法二:super()
class Vehicle: #定义交通工具类 Country='China' def __init__(self,name,speed,load,power): self.name=name self.speed=speed self.load=load self.power=power def run(self): print('开动啦...') class Subway(Vehicle): #地铁 def __init__(self,name,speed,load,power,line): #super(Subway,self) 就相当于实例本身 在python3中super()等同于super(Subway,self) super().__init__(name,speed,load,power) self.line=line def run(self): print('地铁%s号线欢迎您' %self.line) super(Subway,self).run()