博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面向对象(二)--继承与派生、组合
阅读量:4541 次
发布时间:2019-06-08

本文共 5083 字,大约阅读时间需要 16 分钟。

一、什么是继承

继承是一种创建新类的方式,新建的类可以继承一个或多个父类(python支持多继承),父类又可称为基类或超类,新建的类称为派生类或子类。

二、继承的特点

1.继承描述的是事物的遗传关系,子类可以重用父类的属性,需要注意的是:继承是类与类之间的关系!!好处就是可以减少类之间的代码冗余问题

2.在Python中支持一个子类继承多个父类

3.Python类分为两种:新式类、经典类

  (1)新式类: 但凡继承了object的类Foo,以及该类的子类...都是新式类

    在python3中一个类即便是没有显式地继承任何类,默认就会继承object,即python3中所有的类都是新式类

  (2)经典类:没有继承object的类,以及该类的子类...都是经典类

    在python2中才区分新式类与经典类,在python2中一个类如果没有显式地继承任何类,也不会继承object

三、单继承和多继承

class Parent1():    a = 3class Parent2():   a = 3class Sub1(Parent1):         # 单继承,父类是Parent1,子类是Sub1    a = 2    passclass Sub2(Parent1,Parent2):       # 多继承,父类是Parent1,Parent2,子类是Sub1    a = 2    pass

四、查看继承

利用__bases__方法可以查看子类的父类,只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类class Parent1():    passclass Sub1(Parent1):    passprint(Sub1.__bases__)

五、继承的实现原理

C3算法与方法解析顺序(MRO)列表

属性查找的原则:

  1. 子类先于父类被查找
  2. 有多个父类时,会根据它们在列表中的顺序被查找
  3. 如果对下一个类存在两个合法的选择,则选择第一个父类

mro列表只适用于新式类,经典类不存在mro列表

只有在python2中才有经典类与新式类的区分,python3中全部是新式类

六、子类重用父类中的方法(派生)

1、派生:在子类中定义自己的属性,如果与父类的属性重名,那以自己的为准

2、在子类派生出的新方法中重用父类功能的方式一:指名道姓地访问父类中的函数

  Foo.__init__(self,name,age)     不能自动传值,有几个参数就传几个

(1)该方式与继承无关

(2)没有自动传值的效果

class People():    def __init__(self, name, age, sex):        self.name = name        self.age = age        self.sex = sexclass Student(People):    def __init__(self, name, age, sex, score=0):        # 方式一 调用父类中的__init__函数        People.__init__(self, name, age, sex)        self.score = score    def choose(self):        print('%s choosing course' % self)class Teacher(People):    def score(self, stu, score):        stu.score = scorestu = Student('张三', 12, 'male')print(stu.__dict__)      # __dict__可以查看对象的名称空间中的名字
方式一

3、在子类派生出的新方法中重用父类功能的方式二:super(),只能在子类中用

  super().__init__(name,age)    自动传值

(1)在python2中:super(自己的类名,自己的对象)

  在python3:super()    

  调用super()会得到一个特殊的对象,该特殊的对象是专门用来引用父类中的属性的,!!!完全参照mro列表!!!

(2)super()注意点:

  a. 该方式与继承严格依赖于继承的mro列表,类名.mro()      ===>  不管有没有继承关系,super()都是根据mro往后查找

  b. 访问是绑定方法,有自动传值的效果

class People():    def __init__(self, name, age, sex):        self.name = name        self.age = age        self.sex = sexclass Student(People):    def __init__(self, name, age, sex, score=0):        super().__init__(name,age,sex)        self.score = score    def choose(self):        print('%s choosing course' % self)class Teacher(People):    def score(self, stu, score):        stu.score = scorestu = Student('张三', 12, 'male')print(stu.__dict__)  # 查看对象的名称空间
方式二

七、继承背景下的属性查找

1、单继承背景下的属性查找

单继承背景下属性查找顺序:对象的名称空间------>对象的类的名称空间------->父类的名称空间

class Foo:     x=333     passclass Bar(Foo):#     x=222     passobj=Bar()# obj.x=111print(obj.x)   # 333
单继承背景下的属性查找

2、多继承背景下的属性查找

多继承背景下属性查找的顺序:对象的名称空间------>对象的类的名称空间-------->按照从左往右的顺序一个一个的分支找下去

# 查找顺序是 obj-->A-->B-->E-->C-->F-->I-->D-->H#第四层class I:    # x='I'    pass#第三层class E:    # x='E'    passclass F(I):    # x='F'    passclass H:    x='H'# 第二层class B(E):    # x='B'    passclass C(F):    # x='C'    passclass D(H):    # x='D'    pass#第一层class A(B,C,D):    # x='A'    passobj=A()# obj.x=111print(obj.x)
多继承背景下属性查找

八、继承顺序

1、在Java和C#中子类只能继承一个父类,而Python中子类可以同时继承多个父类,如A(B,C,D)

2、如果继承关系为非菱形结构,则会按照先找B这一条分支,然后再找C这一条分支,最后找D这一条分支的顺序直到找到我们想要的属性

如果继承关系为菱形结构,那么属性的查找方式有两种,分别是:深度优先和广度优先

九、组合

1、什么是组合

组合指的是某一个对象拥有一个属性,该属性的值是另外一个类的对象

class Foo():    passclass Bar():    passobj=Bar()obj.attrib=Foo()

2、组合的作用

通过为某一个对象添加属性(属性值是另外一个类的对象)的方式,可以间接地将两个类关联/整合/组合到一起,从而减少类与类之间代码冗余

3、组合的使用

class OldboyPeople:    school = 'oldboy'    def __init__(self, name, age, sex):        self.name = name        self.age = age        self.sex = sexclass OldboyStudent(OldboyPeople):    def __init__(self, name, age, sex, score=0):        super().__init__(name, age, sex)        self.score = score        self.courses = []    def choose_course(self):        print('%s choosing course' % self.name)    def tell_all_course(self):        print(('学生[%s]的课程如下' % self.name).center(60, '='))        for course in self.courses:            course.tell_course()        print('=' * 80)class OldboyTeacher(OldboyPeople):    def __init__(self, name, age, sex, level):        super().__init__(name, age, sex)        self.level = level        self.courses = []    def score(self, stu, num):        stu.score = num    def tell_all_course(self):        print(('老师[%s]教授的课程如下' % self.name).center(70, '-'))        for course in self.courses:            course.tell_course()        print('-' * 80)class Course:    def __init__(self, c_name, c_price, c_period):        self.c_name = c_name        self.c_price = c_price        self.c_period = c_period    def tell_course(self):        print('
<课程名:%s 价格:%s 时间:%s>
' % (self.c_name, self.c_price, self.c_period))python = Course('python全栈开发', 10000, 5)linux = Course('linux架构', 12000, 5)stu = OldboyStudent('zs', 18, 'male')stu.courses.append(python)stu.courses.append(linux)stu.tell_all_course()teach = OldboyTeacher('egon', 18, 'male', 10)teach.courses.append(python)teach.tell_all_course()
组合的使用

 

软件重用的重要方式除了继承之外的另一种方式就是组合。

组合和继承都是有效的利用已有类的资源的重要方式,但使用场景和概念却都不同:

1、继承的方式:

  通过继承建立了派生类与基类之间的关系,是一种“是”的关系。

2、组合的方式:

  用组合的方式建立了类与组合的类之间的关系,是一种“有”的关系。

#当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合会更好。

转载于:https://www.cnblogs.com/zhangbingsheng/p/10115017.html

你可能感兴趣的文章
CTF-练习平台-Misc之 中国菜刀,不再web里?
查看>>
Mac系统配置JDK环境变量
查看>>
多项式累加
查看>>
剑指offer(18)二叉搜索树的后续遍历
查看>>
微信小程序一笔记账开发进度四
查看>>
bzoj 1070 费用流
查看>>
201671010139 徐楠 第四周总结
查看>>
JAVA链表简单实现
查看>>
[转载]T-SQL(MSSQL)语句查询执行顺序
查看>>
SignalR 行实时通信最大连接数
查看>>
开发进度6
查看>>
php方法重载
查看>>
三次握手和四次挥手(二)
查看>>
MySQL中的索引
查看>>
Android开发之手势滑动(滑动手势监听)详解
查看>>
switch
查看>>
HTTP错误code大全
查看>>
PAT Advanced Level 1043
查看>>
决策树基础
查看>>
献给程序员之如何与陌生人交谈
查看>>