码迷,mamicode.com
首页 > 编程语言 > 详细

python-继承与重用

时间:2019-01-17 17:41:29      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:title   抽取类   computer   相同   __init__   方式   分享图片   info   检查   

什么是继承?

继承是一种创建新类的方式,新建的类可以继承一个或多个父类(python支持多继承),父类又可称为基类或超类,新建的类称为派生类或子类。子类会“”遗传”父类的属性,从而解决代码重用问题(比如练习7中Garen与Riven类有很多冗余的代码)

单继承与多继承

class ParentClass_one: #定义父类
pass

class ParentClass_two: #定义父类
pass

class SubClass_one(ParentClass_one): #单继承,基类是ParentClass1,派生类是SubClass
pass

class SubClass_two(ParentClass_one,ParentClass_two): #python支持多继承,用逗号分隔开多个继承的类
pass

经典类与新式类

  • 只有在python2中才分新式类和经典类,python3中统一都是新式类
  • 在python2中,没有显式的继承object类的类,以及该类的子类,都是经典类
  • 在python2中,显式地声明继承object的类,以及该类的子类,都是新式类
  • 在python3中,无论是否继承object,都默认继承object,即python3中所有类均为新式类

继承与抽象

  • 继承描述的是子类与父类之间的关系,是一种什么是什么的关系。要找出这种关系,必须先抽象再继承,抽象即抽取类似或者说比较像的部分。抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度)
  • 继承是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类

继承与重用性

在开发程序的过程中,如果我们定义了一个类A,然后又想新建立另外一个类B,但是类B的大部分内容与类A的相同时,则不需要从头开始写一个类B,只需要通过继承的方式新建类B,让B继承A,B会‘遗传’A的所有属性(数据属性和函数属性),实现代码重用

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 Garen(Hero):
pass

class Riven(Hero):
pass

g=Garen(草丛伦,100,300)
r=Riven(锐雯雯,57,200)

print(g.life_value)
r1.attack(g)
print(g.life_value)

‘‘‘
运行结果
243
‘‘‘
ps:像g.life_value之类的属性引用,会先从实例中找life_value然后去类中找,然后再去父类中找...直到最顶级的父类。

派生

子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准。

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)

r=Riven(锐雯雯,57,200,比基尼)
r.fly()
print(r.skin)

‘‘‘
运行结果
锐雯雯 is flying
比基尼

‘‘‘

组合与重用性

组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合

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属性

r=Riven(锐雯雯)
print(r.equip.fire()) #可以使用组合的类产生的对象所持有的方法

‘‘‘
release Fire skill
‘‘‘

组合与继承

  • 继承的方式:通过继承建立了派生类与基类之间的关系,它是一种‘是‘的关系,比如白马是马,人是动物。当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如老师是人,学生是人
  • 组合的方式:用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python和linux课程,教授有学生s1、s2、s3...

ps:当类之间有显著不同,并且较小的类是较大的类所需要的组件时,使用组合比较好

class People:
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex

class Course:
def __init__(self,name,period,price):
self.name=name
self.period=period
self.price=price
def tell_info(self):
print(<%s %s %s> %(self.name,self.period,self.price))

class Teacher(People):
def __init__(self,name,age,sex,job_title):
People.__init__(self,name,age,sex)
self.job_title=job_title
self.course=[]
self.students=[]


class Student(People):
def __init__(self,name,age,sex):
People.__init__(self,name,age,sex)
self.course=[]


jack=Teacher(jack,18,male,computer teacher)
s=Student(tom,18,female)

python=Course(python,3mons,3000.0)
linux=Course(python,3mons,3000.0)

#为老师jack和学生s1添加课程
jack.course.append(python)
jack.course.append(linux)
s.course.append(python)

#为老师jack添加学生s
jack.students.append(s)


#使用
for obj in jack.course:
obj.tell_info()

继承实现原理

在Java和C#中子类只能继承一个父类,而Python中子类可以同时继承多个父类,如A(B,C,D),如果继承关系为非菱形结构,则会按照先找B这一条分支,然后再找C这一条分支,最后找D这一条分支的顺序直到找到我们想要的属性,如果继承关系为菱形结构,那么属性的查找方式有两种,分别是:深度优先和广度优先
技术分享图片

 

技术分享图片

 

def test(self):
print(from A)

class B(A):
def test(self):
print(from B)

class C(A):
def test(self):
print(from C)

class D(B):
def test(self):
print(from D)

class E(C):
def test(self):
print(from E)

class F(D,E):
# def test(self):
# print(‘from F‘)
pass
f1=F()
f1.test()
print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性

#新式类继承顺序:F->D->B->E->C->A
#经典类继承顺序:F->D->B->A->E->C
#python3中统一都是新式类
#pyhon2中才分新式类与经典类

Python实现继承

python是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,比如:F.mro() #等同于F.__mro__:[<class ‘__main__.F‘>, <class ‘__main__.D‘>, <class ‘__main__.B‘>, <class ‘__main__.E‘>, <class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘object‘>],为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:

  • 子类会先于父类被检查
  • 多个父类会根据它们在列表中的顺序被检查
  • 如果对下一个类存在两个合法的选择,选择第一个父类

子类调用父类的方法
方法一:指名道姓,即父类名.父类方法()

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)

line13=Subway(中国地铁,180m/s,1000人/箱,,13)
line13.run()、

方法二: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()

class Mobike(Vehicle):#摩拜单车
pass

line13=Subway(中国地铁,180m/s,1000人/箱,,13)
line13.run()

 

python-继承与重用

标签:title   抽取类   computer   相同   __init__   方式   分享图片   info   检查   

原文地址:https://www.cnblogs.com/dragon-123/p/10283204.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!