一、组合

  1. '''
  2. 1、什么是组合
  3. 组合就是一个类的对象具备某一个属性,该属性的值是指向另外一个类的对象
  4.  
  5. 2、为何用组合
  6. 组合也是用来解决类与类直接代码冗余问题的
  7.  
  8. 3、如何用组合
  9.  
  10. '''
  11. # 继承减少代码冗余,但是将类与类进行了强耦合,python不崇尚,所以能不用继承就尽量不用继承
  12. class OldboyPeople:
  13. school = 'oldboy'
  14.  
  15. def __init__(self, name, age, sex):
  16. self.name = name
  17. self.age = age
  18. self.sex = sex
  19.  
  20. class OldboyStudent(OldboyPeople):
  21. def __init__(self,name,age,sex,stu_id):
  22. OldboyPeople.__init__(self,name,age,sex)
  23. self.stu_id=stu_id
  24.  
  25. def choose_course(self):
  26. print('%s is choosing course' %self.name)
  27.  
  28. class OldboyTeacher(OldboyPeople):
  29.  
  30. def __init__(self, name, age, sex, level):
  31. OldboyPeople.__init__(self,name,age,sex) #重用父类中的属性(功能)(减少代码冗余)------普通的函数传参,该传几个参数传几个参数
  32. self.level=level
  33.  
  34. def score(self,stu,num): #老师有修改学生成绩的功能,所以将学生对象和修改的成绩传入
  35. stu.score=num
  36. print('老师[%s]为学生[%s]打分[%s]' %(self.name,stu.name,num))
  37.  
  38. stu1=OldboyStudent('猪哥',19,'male',1)
  39. tea1=OldboyTeacher('egon',18,'male',10)
  40.  
  41. stu1.choose_course() #学生对象选择课程------猪哥 is choosing course
  42. tea1.score(stu1,100) #对象的绑定方法--------老师[egon]为学生[猪哥]打分[100]
  43. print(stu1.__dict__) #查看学生的字典属性----{'name': '猪哥', 'age': 19, 'sex': 'male', 'stu_id': 1, 'score': 100}
  44.  
  45. # #定制课程类
  46. class Course: #将学生和老师对象都有课程属性,所以将他们都有的属性抽出来,重新定义了一个课程类
  47. def __init__(self,name,period,price): #调用类时自动触发
  48. self.name=name
  49. self.period=period
  50. self.price=price
  51. # 查看课程信息
  52. def tell_info(self):
  53. msg="""
  54. 课程名:%s
  55. 课程周期:%s
  56. 课程价钱:%s
  57. """ %(self.name,self.period,self.price)
  58. print(msg)
  59. #定制人类--------老师和学生类都是人类
  60. class OldboyPeople:
  61. school = 'oldboy'
  62. # 定制人类独有的数据属性
  63. def __init__(self, name, age, sex):
  64. self.name = name
  65. self.age = age
  66. self.sex = sex
  67.  
  68. class OldboyStudent(OldboyPeople):
  69. def __init__(self,name,age,sex,stu_id):
  70. OldboyPeople.__init__(self,name,age,sex) #类直接点类体代码的函数属性,在子类中重用父类功能,就是一个普通的函数
  71. self.stu_id=stu_id #子类派生出自己独有的数据属性
  72.  
  73. def choose_course(self): #子类派生出自己独有的数据属性
  74. print('%s is choosing course' %self.name)
  75.  
  76. class OldboyTeacher(OldboyPeople):
  77.  
  78. def __init__(self, name, age, sex, level):
  79. OldboyPeople.__init__(self,name,age,sex) #子类重用父类中的方法
  80. self.level=level #子类中派生出自己独有的属性
  81.  
  82. def score(self,stu,num): #子类派生出自己独有的函数属性
  83. stu.score=num
  84. print('老师[%s]为学生[%s]打分[%s]' %(self.name,stu.name,num))
  85.  
  86. # 创造课程----------------------------------对象
  87. python=Course('python全栈开发','5mons',3000) #调用课程对象,产生课程对象,并自动触发__init__函数的执行
  88. linux=Course('linux运维','5mons',800)
  89. # python.tell_info() #课程对象直接绑定课程类下的方法,并将课程对象当做第一个对象自动传入
  90. # linux.tell_info()
  91.  
  92. # 创造学生与老师-----------------------------对象
  93. stu1=OldboyStudent('猪哥',19,'male',1)
  94. tea1=OldboyTeacher('egon',18,'male',10)
  95.  
  96. # 重点
  97. # 将学生、老师与课程对象关联/组合-------------将对象之间进行关联
  98. # --------------------------关键-----------------------------------------------
  99. stu1.course=python #---------------将学生对象stu1与课程对象python关联
  100. tea1.course=linux #---------------将老师对象stu1与课程对象linux关联
  101. # --------------------------关键-----------------------------------------------
  102. '''组合就是一个类的对象具备某一个属性,该属性的值是指向另外一个类的对象'''
  103. # 即学生类产生的学生对象具备课程的属性,该课程的属性值是指向课程类中的课程对象的
  104.  
  105. stu1.course.tell_info() #--------------等价于python.tell_info(),会打印出学生的课程信息
  106. tea1.course.tell_info() #--------------等价于linux.tell_info(),会打印出老师的课程信息

二、菱形继承问题

  1. #coding:utf-8
  2. '''
  3. 1、菱形继承
  4. 当一个子继承多个父类时,多个父类最终继承了同一个类,称之为菱形继承
  5.  
  6. 2、菱形继承的问题:
  7. python2区分经典类与新式类,如果子的继承是一个菱形继承,那么经典类与形式的区别为?
  8. 经典类下查找属性:深度优先查找-----------------一条道走到黑
  9. 新式类下查找属性:广度优先查找------------------最后才去找菱形的端点
  10. '''
  11.  
  12. class G(object):
  13. # def test(self):
  14. # print('from G')
  15. pass
  16.  
  17. class E(G):
  18. # def test(self):
  19. # print('from E')
  20. pass
  21.  
  22. class B(E):
  23. # def test(self):
  24. # print('from B')
  25. pass
  26.  
  27. class F(G):
  28. # def test(self):
  29. # print('from F')
  30. pass
  31.  
  32. class C(F):
  33. # def test(self):
  34. # print('from C')
  35. pass
  36.  
  37. class D(G):
  38. # def test(self):
  39. # print('from D')
  40. pass
  41.  
  42. class A(B,C,D):
  43. def test(self):
  44. print('from A')
  45. # pass
  46.  
  47. obj=A()
  48. #C3算法只试用新式类,经典类不适用
  49. print(A.mro()) #mro是一种C3算法,[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class '__main__.G'>, <class 'object'>]
  50. obj.test() #A->B->E-C-F-D->G-object-------对象属性的查找会严格按照mro列表的顺序进行查找

三、在子类派生的新方法中重用父类功能的两种方式

  1. # 在子派生的新方法中重用父类功能的两种方式
  2. # 方式一:与继承无关
  3. #指名道姓法,直接用:类名.函数名
  4. class OldboyPeople:
  5. school = 'oldboy'
  6. def __init__(self, name, age, sex):
  7. self.name = name
  8. self.age = age
  9. self.sex = sex
  10.  
  11. class OldboyStudent(OldboyPeople):
  12. def __init__(self,name,age,sex,stu_id):
  13. OldboyPeople.__init__(self,name,age,sex) #-------(减少代码冗余)指名道姓法,直接用:类名.函数名,按照函数传参的规则进行传参即可
  14. self.stu_id=stu_id #子类派生出自己独有的数据属性
  15.  
  16. def choose_course(self): #子类派生出自己的函数属性
  17. print('%s is choosing course' %self.name)
  18.  
  19. # 方式二:严格以mro列表继承属性查找关系
  20. # super()会得到一个特殊的对象,该对象就是专门用来访问父类中的属性的(按照继承的关系)
  21. # super().__init__(不用为self传值)------------可以理解为super()是一个特殊的对象,所以对象绑定方法有一个自动传值的效果
  22. # 注意:
  23. # super的完整用法是super(自己的类名,self),在python2中需要写完整,而python3中可以简写为super()
  24. class OldboyPeople:
  25. school = 'oldboy'
  26.  
  27. def __init__(self, name, age, sex):
  28. self.name = name
  29. self.age = age
  30. self.sex = sex
  31.  
  32. class OldboyStudent(OldboyPeople):
  33. # 定制学生类的数据属性,在定制数据属性的过程中,重用了父类中的数据属性
  34. def __init__(self,name,age,sex,stu_id):
  35. # OldboyPeople.__init__(self,name,age,sex) #------父类功能重用方法一
  36. super(OldboyStudent,self).__init__(name,age,sex) #------父类功能重用方法二
  37. self.stu_id=stu_id
  38. #定制学生类的函数属性
  39. def choose_course(self):
  40. print('%s is choosing course' %self.name)
  41.  
  42. stu1=OldboyStudent('猪哥',19,'male',1)
  43. print(stu1.__dict__) #-------查看学生对象的字典属性,{'name': '猪哥', 'age': 19, 'sex': 'male', 'stu_id': 1}
  44. print(OldboyStudent.mro()) #------查看学生类的继承关系,[<class '__main__.OldboyStudent'>, <class '__main__.OldboyPeople'>, <class 'object'>]
  45.  
  46. # 继承顺序查找再应用:
  47. class A:
  48. def f1(self):
  49. print('A.f1')
  50. class B:
  51. def f2(self):
  52. super().f1() #B类和A类没有继承关系,但是会按照mro列表,从该类的下一个类继续进行查找,即此时会到A中进行查找
  53. print('B.f2')
  54.  
  55. class C(B,A):
  56. pass
  57.  
  58. obj=C()
  59. print(C.mro()) #C-》B->A->object,查看C类的继承关系,[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
  60. obj.f2() #对象属性的查找会严格按照mro列表的顺序进行查找,自己的对象没有到自己的类中找,自己的类中没有,到父类中找,此时父类查找的先后顺序就是按照mro列表来的
  61.  
  62. # 打印结果:
  63. '''
  64. A.f1
  65. B.f2
  66. '''

四、多态与多态性

  1. '''
  2. 1 什么是多态
  3. 多态指的是同一种事物的多种形态
  4. 水-》冰、水蒸气、液态水
  5. 动物-》人、狗、猪
  6.  
  7. 2 为和要用多态
  8. 多态性:
  9. 继承同一个类的多个子类中有相同的方法名
  10. 那么子类产生的对象就可以不用考虑具体的类型而直接调用功能
  11.  
  12. 3 如何用
  13. '''
  14. import abc
  15. class Animal(metaclass=abc.ABCMeta): #定义一个抽象类,规范一个类的类(统一成一套标准)
  16. @abc.abstractmethod #装饰器装饰后,意味着但凡继承类该类的方法,函数属性的属性名都必须与父类的函数属性名一致,否则就会报错
  17. def speak(self):
  18. pass
  19. @abc.abstractmethod 子类此时就必须与父类拥有相同的方法名,否则实例化就会报错
  20. def eat(self):
  21. pass
  22.  
  23. # Animal() #强调:父类是用来制定标准的,不能被实例化-------此时实例化就会报错,这并不是python崇尚的,python更多的是一种约定俗成的,而不是硬性的限制
  24. class People(Animal):
  25. def speak(self):
  26. print('say hello')
  27.  
  28. def eat(self):
  29. pass
  30.  
  31. class Dog(Animal):
  32. def speak(self):
  33. print('汪汪汪')
  34.  
  35. def eat(self):
  36. pass
  37. class Pig(Animal):
  38. def speak(self):
  39. print('哼哼哼')
  40.  
  41. def eat(self):
  42. pass
  43.  
  44. peo1=People()
  45. dog1=Dog()
  46. pig1=Pig()
  47. #
  48. #继承同一个动物类的多个子类(人、狗、猪类)中有相同的方法名(speak\eat),那么子类产生的对象就可以不用考虑具体的类型而直接调用功能
  49. peo1.speak() #不用考虑具体的对象类型,而直接调用speak的功能
  50. dog1.speak()
  51. pig1.speak()
  52.  
  53. # -----------------------不用考虑是什么动物来调用speak的函数属性,所以将其封装成一个功能-----------------------------------
  54. def my_speak(animal):
  55. animal.speak()
  56. my_speak(peo1)
  57. my_speak(dog1)
  58. my_speak(pig1)
  59. # -----------------------不用考虑是什么动物来调用speak的函数属性,所以将其封装成一个功能-----------------------------------
  60.  
  61. # 不同的数据类型,他们都有统计长度的这个方法,所以我们想到的是将他们制定成一套方法,便于对不同的数据类型进行统计
  62. l=[1,2,3]
  63. s='helllo'
  64. t=(1,2,3)
  65.  
  66. print(l.__len__()) #用同一种形式去调用的好处就是将其功能封装成一个函数时,只需要传入对象就可以了
  67. print(s.__len__()) #如果用不同的方法名去统计不同数据类型的长度,这样封装成函数时就需要制定不同的函数去封装
  68. print(t.__len__())
  69.  
  70. # def len(obj):
  71. # return obj.__len__()
  72.  
  73. print(len(l)) # l.__len__()
  74. print(len(s)) #s.__len__()
  75. print(len(t))
  76.  
  77. # python推崇的是鸭子类型,只要你叫的声音像鸭子,并且你走路的样子也像鸭子,那你就是鸭子
  78. class Disk:
  79. def read(self):
  80. print('disk read')
  81.  
  82. def write(self):
  83. print('disk wirte')
  84.  
  85. class Process:
  86. def read(self):
  87. print('process read')
  88.  
  89. def write(self):
  90. print('process wirte')
  91.  
  92. class File:
  93. def read(self):
  94. print('file read')
  95.  
  96. def write(self):
  97. print('file wirte')
  98.  
  99. obj1=Disk()
  100. obj2=Process()
  101. obj3=File()
  102.  
  103. obj1.read()
  104. obj1.write()

Python之面向对象的组合、多态、菱形问题、子类中重用父类的两种方式的更多相关文章

  1. [面向对象之继承应用(在子类派生重用父类功能(super),继承实现原理(继承顺序、菱形问题、继承原理、Mixins机制),组合]

    [面向对象之继承应用(在子类派生重用父类功能(super),继承实现原理(继承顺序.菱形问题.继承原理.Mixins机制),组合] 继承应用 类与类之间的继承指的是什么'是'什么的关系(比如人类,猪类 ...

  2. python之子类调用父类的两种方式

    第一种方式 直接在子类中调用父类名: Vehicle.__init__(self,name,speed,load,power)#调用父类的实例 Vehicle.run(self) #调用父类的方法 # ...

  3. javascript消除字符串两边空格的两种方式,面向对象和函数式编程。python oop在调用时候的优点

    主要是javascript中消除字符串空格,比较两种方式的不同 //面向对象,消除字符串两边空格 String.prototype.trim = function() { return this.re ...

  4. python基础----继承与派生、组合、接口与归一化设计、抽象类、子类中调用父类方法

    一.什么是继承                                                                          继承是一种创建新的类的方式,在pyth ...

  5. python基础之类的继承与派生、组合、接口与归一化设计、抽象类、子类中调用父类方法

    一.什么是继承 继承是一种创建新的类的方式,新建的类可以继承自一个或者多个父类,原始类称为基类或超类,新建的类称为派生类或子类. 派生:子类继承了父类的属性,然后衍生出自己新的属性,如果子类衍生出的新 ...

  6. 基础知识:编程语言介绍、Python介绍、Python解释器安装、运行Python解释器的两种方式、变量、数据类型基本使用

    2018年3月19日 今日学习内容: 1.编程语言的介绍 2.Python介绍 3.安装Python解释器(多版本共存) 4.运行Python解释器程序两种方式.(交互式与命令行式)(♥♥♥♥♥) 5 ...

  7. 周一02.3运行python程序的两种方式

    一.运行python程序的两种方式 方法一:交互式:                     优点:输入一行代码立刻返回结果                      缺点:无法永久保存代码 方法二: ...

  8. Python字符串的两种方式——百分号方式,format的方式

    Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...

  9. 执行python解释器的两种方式

    执行python解释器的两种方式 1.交互式 python是高级语言,是解释型语言,逐行翻译,写一句翻译一句 print ('hello world') 2.命令行式 python和python解释器 ...

随机推荐

  1. [UI] Article intro effects

    Article intro effects http://freebiesbug.com/code-stuff/article-intro-effects/

  2. django 实用工具dj-database-url 快速配置数据库

    dj-database-url Github>>> django快速配置多种数据库 $ pip install dj-database-url Configure your data ...

  3. docker 自制CentOS 6-lnp镜像

    环境准备 1台centos 6.5镜像虚拟机  febootstrap.docker febootstrap 安装 yum install -y yum-priorities && r ...

  4. C++ Boost在Windows和Linux下的编译安装

    再debian下直接apt-get install gcc g++就可以了.按照类似的逻辑,再Fedora下yum install gcc g++ 报告无法找到g++包. 差了一下,原来这个包的名字叫 ...

  5. Echarts 多曲线“断点”问题解决方法

    Echarts 用来做可视化曲线是非常优秀的一个库.建议使用 Echarts 作为项目的可视化图标库时,仔细研究 官方实例,根据需求来选择类似的示例,下载实例模板来开发,节省时间,减少出错,提高效率. ...

  6. 用python解析word文件(三):style

    太长了,我决定还是拆开三篇写.   (一)段落篇(paragraph) (二)表格篇(table) (三)样式篇(style)(本篇) 选你所需即可.下面开始正文. 在前两篇中,我们已经解析出了par ...

  7. Linux - 版本控制系统SVN

    0. 摘要 本文通过搭建SVN多版本库为例,介绍SVN的使用. SVN是一个集中式版本控制系统,在服务端部署中央版本库,所有开发人员客户端连接到中央版本库进行代码的提交和更新. Apache Subv ...

  8. C 六学家的困惑 【YY】 (2019年华南理工大学程序设计竞赛(春季赛))

    冲鸭,去刷题:https://ac.nowcoder.com/acm/contest/625/C 小六喜欢两全其美的事情,今天就正好有一个这样的机会. 小六面前有两根管子,管子里面放满了数字为1到9的 ...

  9. JavaScript 空位补零实现代码

    实现一: 复制代码代码如下: /* 平淡无奇法 */ function pad(num, n) { var i = (num + "").length; while(i++ < ...

  10. VC++获取当前路径及程序名的实现代码

    VC上或取当前路径有多种方法,最常用的是使用 GetCurrentDirectory和GetModuleFileName函数,个中都有诸多注意事项,特别总结一下 一.获取当前运行目录的绝对路径 1.使 ...