一、组合

'''
1、什么是组合
组合就是一个类的对象具备某一个属性,该属性的值是指向另外一个类的对象 2、为何用组合
组合也是用来解决类与类直接代码冗余问题的 3、如何用组合 '''
# 继承减少代码冗余,但是将类与类进行了强耦合,python不崇尚,所以能不用继承就尽量不用继承
class OldboyPeople:
school = 'oldboy' def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex class OldboyStudent(OldboyPeople):
def __init__(self,name,age,sex,stu_id):
OldboyPeople.__init__(self,name,age,sex)
self.stu_id=stu_id def choose_course(self):
print('%s is choosing course' %self.name) class OldboyTeacher(OldboyPeople): def __init__(self, name, age, sex, level):
OldboyPeople.__init__(self,name,age,sex) #重用父类中的属性(功能)(减少代码冗余)------普通的函数传参,该传几个参数传几个参数
self.level=level def score(self,stu,num): #老师有修改学生成绩的功能,所以将学生对象和修改的成绩传入
stu.score=num
print('老师[%s]为学生[%s]打分[%s]' %(self.name,stu.name,num)) stu1=OldboyStudent('猪哥',19,'male',1)
tea1=OldboyTeacher('egon',18,'male',10) stu1.choose_course() #学生对象选择课程------猪哥 is choosing course
tea1.score(stu1,100) #对象的绑定方法--------老师[egon]为学生[猪哥]打分[100]
print(stu1.__dict__) #查看学生的字典属性----{'name': '猪哥', 'age': 19, 'sex': 'male', 'stu_id': 1, 'score': 100} # #定制课程类
class Course: #将学生和老师对象都有课程属性,所以将他们都有的属性抽出来,重新定义了一个课程类
def __init__(self,name,period,price): #调用类时自动触发
self.name=name
self.period=period
self.price=price
# 查看课程信息
def tell_info(self):
msg="""
课程名:%s
课程周期:%s
课程价钱:%s
""" %(self.name,self.period,self.price)
print(msg)
#定制人类--------老师和学生类都是人类
class OldboyPeople:
school = 'oldboy'
# 定制人类独有的数据属性
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex class OldboyStudent(OldboyPeople):
def __init__(self,name,age,sex,stu_id):
OldboyPeople.__init__(self,name,age,sex) #类直接点类体代码的函数属性,在子类中重用父类功能,就是一个普通的函数
self.stu_id=stu_id #子类派生出自己独有的数据属性 def choose_course(self): #子类派生出自己独有的数据属性
print('%s is choosing course' %self.name) class OldboyTeacher(OldboyPeople): def __init__(self, name, age, sex, level):
OldboyPeople.__init__(self,name,age,sex) #子类重用父类中的方法
self.level=level #子类中派生出自己独有的属性 def score(self,stu,num): #子类派生出自己独有的函数属性
stu.score=num
print('老师[%s]为学生[%s]打分[%s]' %(self.name,stu.name,num)) # 创造课程----------------------------------对象
python=Course('python全栈开发','5mons',3000) #调用课程对象,产生课程对象,并自动触发__init__函数的执行
linux=Course('linux运维','5mons',800)
# python.tell_info() #课程对象直接绑定课程类下的方法,并将课程对象当做第一个对象自动传入
# linux.tell_info() # 创造学生与老师-----------------------------对象
stu1=OldboyStudent('猪哥',19,'male',1)
tea1=OldboyTeacher('egon',18,'male',10) # 重点
# 将学生、老师与课程对象关联/组合-------------将对象之间进行关联
# --------------------------关键-----------------------------------------------
stu1.course=python #---------------将学生对象stu1与课程对象python关联
tea1.course=linux #---------------将老师对象stu1与课程对象linux关联
# --------------------------关键-----------------------------------------------
'''组合就是一个类的对象具备某一个属性,该属性的值是指向另外一个类的对象'''
# 即学生类产生的学生对象具备课程的属性,该课程的属性值是指向课程类中的课程对象的 stu1.course.tell_info() #--------------等价于python.tell_info(),会打印出学生的课程信息
tea1.course.tell_info() #--------------等价于linux.tell_info(),会打印出老师的课程信息

二、菱形继承问题

#coding:utf-8
'''
1、菱形继承
当一个子继承多个父类时,多个父类最终继承了同一个类,称之为菱形继承 2、菱形继承的问题:
python2区分经典类与新式类,如果子的继承是一个菱形继承,那么经典类与形式的区别为?
经典类下查找属性:深度优先查找-----------------一条道走到黑
新式类下查找属性:广度优先查找------------------最后才去找菱形的端点
''' class G(object):
# def test(self):
# print('from G')
pass class E(G):
# def test(self):
# print('from E')
pass class B(E):
# def test(self):
# print('from B')
pass class F(G):
# def test(self):
# print('from F')
pass class C(F):
# def test(self):
# print('from C')
pass class D(G):
# def test(self):
# print('from D')
pass class A(B,C,D):
def test(self):
print('from A')
# pass obj=A()
#C3算法只试用新式类,经典类不适用
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'>]
obj.test() #A->B->E-C-F-D->G-object-------对象属性的查找会严格按照mro列表的顺序进行查找

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

# 在子派生的新方法中重用父类功能的两种方式
# 方式一:与继承无关
#指名道姓法,直接用:类名.函数名
class OldboyPeople:
school = 'oldboy'
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex class OldboyStudent(OldboyPeople):
def __init__(self,name,age,sex,stu_id):
OldboyPeople.__init__(self,name,age,sex) #-------(减少代码冗余)指名道姓法,直接用:类名.函数名,按照函数传参的规则进行传参即可
self.stu_id=stu_id #子类派生出自己独有的数据属性 def choose_course(self): #子类派生出自己的函数属性
print('%s is choosing course' %self.name) # 方式二:严格以mro列表继承属性查找关系
# super()会得到一个特殊的对象,该对象就是专门用来访问父类中的属性的(按照继承的关系)
# super().__init__(不用为self传值)------------可以理解为super()是一个特殊的对象,所以对象绑定方法有一个自动传值的效果
# 注意:
# super的完整用法是super(自己的类名,self),在python2中需要写完整,而python3中可以简写为super()
class OldboyPeople:
school = 'oldboy' def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex class OldboyStudent(OldboyPeople):
# 定制学生类的数据属性,在定制数据属性的过程中,重用了父类中的数据属性
def __init__(self,name,age,sex,stu_id):
# OldboyPeople.__init__(self,name,age,sex) #------父类功能重用方法一
super(OldboyStudent,self).__init__(name,age,sex) #------父类功能重用方法二
self.stu_id=stu_id
#定制学生类的函数属性
def choose_course(self):
print('%s is choosing course' %self.name) stu1=OldboyStudent('猪哥',19,'male',1)
print(stu1.__dict__) #-------查看学生对象的字典属性,{'name': '猪哥', 'age': 19, 'sex': 'male', 'stu_id': 1}
print(OldboyStudent.mro()) #------查看学生类的继承关系,[<class '__main__.OldboyStudent'>, <class '__main__.OldboyPeople'>, <class 'object'>] # 继承顺序查找再应用:
class A:
def f1(self):
print('A.f1')
class B:
def f2(self):
super().f1() #B类和A类没有继承关系,但是会按照mro列表,从该类的下一个类继续进行查找,即此时会到A中进行查找
print('B.f2') class C(B,A):
pass obj=C()
print(C.mro()) #C-》B->A->object,查看C类的继承关系,[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
obj.f2() #对象属性的查找会严格按照mro列表的顺序进行查找,自己的对象没有到自己的类中找,自己的类中没有,到父类中找,此时父类查找的先后顺序就是按照mro列表来的 # 打印结果:
'''
A.f1
B.f2
'''

四、多态与多态性

'''
1 什么是多态
多态指的是同一种事物的多种形态
水-》冰、水蒸气、液态水
动物-》人、狗、猪 2 为和要用多态
多态性:
继承同一个类的多个子类中有相同的方法名
那么子类产生的对象就可以不用考虑具体的类型而直接调用功能 3 如何用
'''
import abc
class Animal(metaclass=abc.ABCMeta): #定义一个抽象类,规范一个类的类(统一成一套标准)
@abc.abstractmethod #装饰器装饰后,意味着但凡继承类该类的方法,函数属性的属性名都必须与父类的函数属性名一致,否则就会报错
def speak(self):
pass
@abc.abstractmethod 子类此时就必须与父类拥有相同的方法名,否则实例化就会报错
def eat(self):
pass # Animal() #强调:父类是用来制定标准的,不能被实例化-------此时实例化就会报错,这并不是python崇尚的,python更多的是一种约定俗成的,而不是硬性的限制
class People(Animal):
def speak(self):
print('say hello') def eat(self):
pass class Dog(Animal):
def speak(self):
print('汪汪汪') def eat(self):
pass
class Pig(Animal):
def speak(self):
print('哼哼哼') def eat(self):
pass peo1=People()
dog1=Dog()
pig1=Pig()
#
#继承同一个动物类的多个子类(人、狗、猪类)中有相同的方法名(speak\eat),那么子类产生的对象就可以不用考虑具体的类型而直接调用功能
peo1.speak() #不用考虑具体的对象类型,而直接调用speak的功能
dog1.speak()
pig1.speak() # -----------------------不用考虑是什么动物来调用speak的函数属性,所以将其封装成一个功能-----------------------------------
def my_speak(animal):
animal.speak()
my_speak(peo1)
my_speak(dog1)
my_speak(pig1)
# -----------------------不用考虑是什么动物来调用speak的函数属性,所以将其封装成一个功能----------------------------------- # 不同的数据类型,他们都有统计长度的这个方法,所以我们想到的是将他们制定成一套方法,便于对不同的数据类型进行统计
l=[1,2,3]
s='helllo'
t=(1,2,3) print(l.__len__()) #用同一种形式去调用的好处就是将其功能封装成一个函数时,只需要传入对象就可以了
print(s.__len__()) #如果用不同的方法名去统计不同数据类型的长度,这样封装成函数时就需要制定不同的函数去封装
print(t.__len__()) # def len(obj):
# return obj.__len__() print(len(l)) # l.__len__()
print(len(s)) #s.__len__()
print(len(t)) # python推崇的是鸭子类型,只要你叫的声音像鸭子,并且你走路的样子也像鸭子,那你就是鸭子
class Disk:
def read(self):
print('disk read') def write(self):
print('disk wirte') class Process:
def read(self):
print('process read') def write(self):
print('process wirte') class File:
def read(self):
print('file read') def write(self):
print('file wirte') obj1=Disk()
obj2=Process()
obj3=File() obj1.read()
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. 封装CoreGraphics的API简化绘图操作

    封装CoreGraphics的API简化绘图操作 效果 说明 1. 将CoreGraphics的API接口抽象为对象,让绘图变得简单易懂 2. 简化常用的绘制操作 3. 源码长期更新 源码 https ...

  2. SQL语言DDL DML DCL TCL四种语言

    1.DDL(Data Definition Language)数据库定义语言:DDL使我们有能力创建或删 除表格.可以定义索引(键),规定表之间的链接,以及施加表间的 约束. • 常见DDL 语句: ...

  3. Linux 系统的/etc目录

    /etc目录下的重要文件 /etc/sysconfig/network 指定服务器上的网络配置信息 /etc/rc.d/init.d/network 网络配置脚本信息 网络配置脚本,开机通过脚本文件来 ...

  4. for/while 循环全部执行完,, 中途不会停下!!中途不会停下!!中途不会停下!!! 中途不会停下!!!!!

    对于这样一个在for 里面的, 他会从开始到最后走走一遍,然后再回到开始, 而不是在里面有两个操作,全部操作完第一个再往下走, 这个和我的学习方法似乎一样,真的要全局来一遍,再从新来一遍回顾问题 下面 ...

  5. Golang channel 用法简介

    channel 是 golang 里相当有趣的一个功能,大部分时候 channel 都是和 goroutine 一起配合使用.本文主要介绍 channel 的一些有趣的用法. 通道(channel), ...

  6. ABAP知识点提纲

    编号 课程名称 课程内容 预计课时 10.1.1~10.1.2 SAP系统与产品集 1. 了解SAP常见产品 ,了解SAP系统架构 1 10.1.3~10.1.4 导航界面与用户界面 1. 了解SAP ...

  7. luogu P3369 【模板】普通平衡树(splay)

    嘟嘟嘟 突然觉得splay挺有意思,唯一不足的是这几天是一天一道,debug到崩溃. 做了几道平衡树基础题后,对这题有莫名的自信,还算愉快的敲完了代码后,发现样例都过不去,然后就陷入了无限的debug ...

  8. 20155314 2016-2017-2《Java程序设计》课程总结

    20155314 2016-2017-2<Java程序设计>课程总结 每周作业链接汇总 预备作业1:刘子健的第一篇博客 预备作业2:刘子健的第二篇博客--有关CCCCC语言(・᷄ᵌ・᷅) ...

  9. mariadb密码问题

    错误信息: Mysql:ERROR 1698 (28000): Access denied for user 'root'@'localhost' 解决办法: sudo cat /etc/mysql/ ...

  10. oracle数据库之操作总结

    ## 连接数据库: sqlplus test/test##@localhost:/ORCL ## 查询数据库所有的表: select table_name from user_tables; ## 查 ...