zoukankan      html  css  js  c++  java
  • python D17 类与类之间的关系

    # 类与类之间的关系
    # 1、以来关系
    # 2、关联关系、组合关系、聚合关系
    # 3、继承关系,self到底是什么鬼?
    # 4、类中的特殊成员

    # 一、类与类之间的以来关系
    # ⼤千世界, 万物之间皆有规则和规律. 我们的类和对象是对⼤千世界中的所有事物进⾏归
    # 类. 那事物之间存在着相对应的关系. 类与类之间也同样如此. 在⾯向对象的世界中. 类与类
    # 中存在以下关系:
    # 1. 依赖关系
    # 2. 关联关系
    # 3. 组合关系
    # 4. 聚合关系
    # 5. 继承关系
    # 6. 实现关系
    # 由于python是⼀⻔弱类型编程语⾔. 并且所有的对象之间其实都是多态的关系. 也就是说,
    # 所有的东⻄都可以当做对象来使⽤. 所以我们在写代码的时候很容易形成以上关系. ⾸先. 我
    # 们先看第⼀种, 也是这些关系中紧密程度最低的⼀个, 依赖关系.

    # ⾸先, 我们设计⼀个场景. 还是最初的那个例⼦. 要把⼤象装冰箱. 注意. 在这个场景中, 其
    # 实是存在了两种事物的. ⼀个是⼤象, ⼤象负责整个事件的掌控者, 还有⼀个是冰箱, 冰箱负
    # 责被⼤象操纵.
    # ⾸先, 写出两个类, ⼀个是⼤象类, ⼀个是冰箱类.
    # class Elphant:
    # def __init__(self, name):
    # self.name = name
    # def open(self):
    # '''
    # 开⻔
    # :return :return:
    # '''
    # pass
    # def close(self):
    # '''
    # 关⻔
    # :return :return:
    # '''
    # pass
    #
    # class Refrigerator:
    # def open_door(self):
    # print("冰箱⻔被打开了")
    #
    # def close_door(self):
    # print("冰箱⻔被关上了")
    # 冰箱的功能非常简单, 只要会开⻔, 关⻔就⾏了. 但是⼤象就没那么简单了. 想想. ⼤象开
    # ⻔和关⻔的时候是不是要先找个冰箱啊. 然后呢? 打开冰箱⻔. 是不是打开刚才找到的那个冰
    # 箱⻔. 然后装⾃⼰. 最后呢? 关冰箱⻔, 注意, 关的是刚才那个冰箱吧. 也就是说. 开⻔和关⻔
    # ⽤的是同⼀个冰箱. 并且. ⼤象有更换冰箱的权利, 想进那个冰箱就进那个冰箱. 这时, ⼤象类
    # 和冰箱类的关系并没有那么的紧密. 因为⼤象可以指定任何⼀个冰箱. 接下来. 我们把代码完
    # 善⼀下.

    # class Elphan:
    # def __init__(self, name):
    # self.name = name
    # def open(self, ref):
    # print("⼤象要开⻔了. 默念三声. 开!")
    # # 由外界传递进来⼀个冰箱, 让冰箱开⻔. 这时. ⼤象不⽤背着冰箱到处跑.
    # # 类与类之间的关系也就不那么的紧密了. 换句话说. 只要是有open_door()⽅法的对象. 都可以接收运⾏
    # ref.open_door()
    #
    # def close(self, ref):
    # print("⼤象要关⻔了. 默念三声. 关!")
    # ref.close_door()
    # def take(self):
    # print("钻进去")
    #
    # class Refrigerator:
    # def open_door(self):
    # print("冰箱⻔被打开了")
    # def close_door(self):
    # print("冰箱⻔被关上了")
    #
    # # 造冰箱
    # r = Refrigerator()
    # # 造⼤象
    # el = Elphan("神奇的⼤象")
    # el.open(r) # 注意. 此时是把⼀个冰箱作为参数传递进去了. 也就是说. ⼤象可以指定任何⼀个冰箱.
    # el.take()
    # el.close(r)
    # 此时, 我们说, ⼤象和冰箱之间就是依赖关系. 我⽤着你. 但是你不属于我. 这种关系是最弱的.
    # 比如. 公司和雇员之间. 对于正式员⼯, 肯定要签订劳动合同. 还得⼩⼼伺候着. 但是如果是兼
    # 职. 那⽆所谓. 需要了你就来. 不需要你就可以拜拜了. 这⾥的兼职(临时⼯) 就属于依赖关系.
    # 我⽤你. 但是你不属于我.

    # ⼆. 关联关系.组合关系, 聚合关系
    # 其实这三个在代码上写法是⼀样的. 但是, 从含义上是不⼀样的.
    # 1. 关联关系. 两种事物必须是互相关联的. 但是在某些特殊情况下是可以更改和更换的.
    # 2. 聚合关系. 属于关联关系中的⼀种特例. 侧重点是xxx和xxx聚合成xxx. 各⾃有各⾃的
    # 声明周期. 比如电脑. 电脑⾥有CPU, 硬盘, 内存等等. 电脑挂了. CPU还是好的. 还是
    # 完整的个体
    # 3. 组合关系. 属于关联关系中的⼀种特例. 写法上差不多. 组合关系比聚合还要紧密. 比
    # 如⼈的⼤脑, ⼼脏, 各个器官. 这些器官组合成⼀个⼈. 这时. ⼈如果挂了. 其他的东⻄
    # 也跟着挂了.

    # ⾸先我们看关联关系: 这个最简单. 也是最常⽤的⼀种关系. 比如. ⼤家都有男女朋友. 男⼈
    # 关联着女朋友. 女⼈关联着男朋友. 这种关系可以是互相的, 也可以是单⽅⾯的

    # class Boy:
    # def __init__(self, name, girlFriend=None):
    # self.name = name
    # self.girlFriend = girlFriend
    # def have_a_dinner(self):
    # if self.girlFriend:
    # print("%s 和 %s⼀起去吃晚餐" % (self.name, self.girlFriend.name))
    # else:
    # print("单身狗. 吃什么饭")
    # class Girl:
    # def __init__(self, name):
    # self.name = name
    #
    # b = Boy("alex")
    # b.have_a_dinner()
    # # 突然⽜B了. 找到⼥朋友了
    # g = Girl("如花")
    # b.girlFriend = g # 有⼥朋友了. 6666
    # b.have_a_dinner()
    # gg = Girl("李⼩花")
    # bb = Boy("wusir", gg) # 娃娃亲. 出⽣就有⼥朋友. 服不服
    # bb.have_a_dinner() # 多么幸福的⼀家
    # # 突然.bb失恋了. 娃娃亲不跟他好了
    # bb.girlFriend = None
    # bb.have_a_dinner() # ⼜单身了.

    # 注意. 此时Boy和Girl两个类之间就是关联关系. 两个类的对象紧密练习着. 其中⼀个没有
    # 了. 另⼀个就孤单的不得了. 关联关系, 其实就是 我需要你. 你也属于我. 这就是关联关系. 像
    # 这样的关系有很多很多. 比如. 学校和老师之间的关系.

    # School --- 学校
    # Teacher--- 老师
    # 老师必然属于⼀个学校. 换句话说. 每个老师肯定有⼀个指定的⼯作机构. 就是学校. 那老师
    # 的属性中必然关联着学校.
    # 一个老师对应一个学校 站在老师这个对象上
    # class School:
    # def __init__(self, name, address):
    # self.name = name
    # self.address = address
    # class Teacher:
    # def __init__(self, name, school=None):
    # self.name = name
    # self.school = school
    # s1 = School("⽼男孩北京校区", "美丽的沙河")
    # s2 = School("⽼男孩上海校区", "迪⼠尼旁边")
    # s3 = School("⽼男孩深圳校区", "南⼭区法院欢迎你")
    # t1 = Teacher("⾦王", s1)
    # t2 = Teacher("银王", s1)
    # t3 = Teacher("海峰", s2)
    # t4 = Teacher("⾼鑫", s3)
    # # 找到⾼鑫所在的校区地址
    # print(t4.school.address)

    # 想想, 这样的关系如果反过来. ⼀个老师可以选⼀个学校任职, 那反过来. ⼀个学校有多少
    # 老师呢? ⼀堆吧? 这样的关系如何来描述呢?
    # 一个学校对应对个老师 一个老师对应一个学校 站在学校这个对象上
    # class School:
    # def __init__(self, name, address):
    # self.name = name
    # self.address = address
    # self.t_list = [] # 每个学校都应该有⼀个装⼀堆⽼师的列表
    # def add_teacher(self, teacher):
    # self.t_list.append(teacher)
    # class Teacher:
    # def __init__(self, name, school=None):
    # self.name = name
    # self.school = school
    # s1 = School("⽼男孩北京校区", "美丽的沙河")
    # s2 = School("⽼男孩上海校区", "迪⼠尼旁边")
    # s3 = School("⽼男孩深圳校区", "南⼭区法院欢迎你")
    # t1 = Teacher("⾦王", s1)
    # t2 = Teacher("银王", s1)
    # t3 = Teacher("海峰", s2)
    # t4 = Teacher("⾼鑫", s3)
    # s1.add_teacher(t1)
    # s1.add_teacher(t2)
    # s1.add_teacher(t3)
    # # 查看沙河校区有哪些⽼师
    # for t in s1.t_list:
    # print(t.name)

    # 好了. 这就是关联关系. 当我们在逻辑上出现了. 我需要你. 你还得属于我. 这种逻辑 就是关
    # 联关系. 那注意. 这种关系的紧密程度比上⾯的依赖关系要紧密的多. 为什么呢? 想想吧
    # ⾄于组合关系和聚合关系. 其实代码上的差别不⼤. 都是把另⼀个类的对象作为这个类的
    # 属性来传递和保存. 只是在含义上会有些许的不同⽽已.

    # 三. 继承关系.
    # 在⾯向对象的世界中存在着继承关系. 我们现实中也存在着这样的关系. 我们说过. x是⼀
    # 种y, 那x就可以继承y. 这时理解层⾯上的. 如果上升到代码层⾯. 我们可以这样认为. ⼦类在不
    # 影响⽗类的程序运⾏的基础上对⽗类进⾏的扩充和扩展. 这⾥.我们可以把⽗类被称为超类或
    # 者基类. ⼦类被称为派⽣类.
    # ⾸先, 类名和对象默认是可以作为字典的key的

    # class Foo:
    # def __init__(self):
    # pass
    # def method(self):
    # pass
    # # __hash__ = None
    # print(hash(Foo))
    # print(hash(Foo()))

    # 既然可以hash. 那就是说字典的key可以是对象或者类
    # dic = {}
    # dic[Foo] = 123
    # dic[Foo()] = 456
    # print(dic) # {<class '__main__.Foo'>: 123, <__main__.Foo object at
    # 0x103491550>: 456}

    # 虽然显⽰的有点⼉诡异. 但是是可以⽤的.
    # 接下来. 我们来继续研究继承上的相关内容. 在本节中主要研究⼀下self. 记住. 不管⽅法之
    # 间如何进⾏调⽤. 类与类之间是何关系. 默认的self都是访问这个⽅法的对象.

    # class Base:
    # def __init__(self, num):
    # self.num = num
    # def func1(self):
    # print(self.num)
    # self.func2()
    # def func2(self):
    # print(111, self.num)
    # class Foo(Base):
    # def func2(self):
    # print(222, self.num)
    # lst = [Base(1), Base(2), Foo(3)]
    # for obj in lst:
    # obj.func1() # 那笔来吧. 好好算
    # 结果
    # 1,
    # 111,1
    # 2,
    # 222,2
    # 3,
    # 222, 3
    # 结论: self就是你访问⽅法的那个对象. 先找⾃⼰, 然后在找⽗类的.

    # 四.类中的特殊成员
    # 什么是特殊成员呢? __init_()
    # 就是⼀个特殊的成员.说⽩了.带双下划线的那⼀坨.这些⽅
    # 法在特殊的场景的时候会被⾃动的执⾏.比如,

    # 1. 类名() 会⾃动执⾏__init__()
    # 2. 对象() 会⾃动执⾏__call__()
    # 3. 对象[key] 会⾃动执⾏__getitem__()
    # 4. 对象[key] = value 会⾃动执⾏__setitem__()
    # 5. del 对象[key] 会⾃动执⾏ __delitem__()
    # 6. 对象+对象 会⾃动执⾏ __add__()
    # 7. with 对象 as 变量 会⾃动执⾏__enter__ 和__exit__
    # 8. 打印对象的时候 会⾃动执⾏ __str__
    # 9. ⼲掉可哈希 __hash__ == None 对象就不可哈希了.

    # 创建对象的真正步骤:
    # ⾸先, 在执⾏类名()的时候. 系统会⾃动先执⾏__new__()来开辟内存. 此时新开辟出来的内
    # 存区域是空的. 紧随其后, 系统⾃动调⽤__init__()来完成对象的初始化⼯作. 按照时间轴来算.
    # 1. 加载类
    # 2. 开辟内存(__new__)
    # 3. 初始化(__init__)
    # 4. 使⽤对象⼲xxxxxxxxx
    #
    # 类似的操作还有很多很多. 我们不需要完全刻意的去把所有的特殊成员全都记住. 实战中也
    # ⽤不到那么多. ⽤到了查就是了.

    # 总结:
    # __new__: 是真正的构造方法(构造内存空间再有__init__)
    # __init__: 是初始化方法
    # 依赖关系:
    # 在方法中给方法传递一个对象. 此时类与类之间的关系是最轻的
    # 关联关系(组合, 聚合):
    # 一对多. 一的一方埋集合
    # 多的一方埋实体
  • 相关阅读:
    tensorflow日志信息如何屏蔽?
    测试图像篡改模型fps逐渐降低的原因?
    np.float32()和np.float64
    hive on spark运行时 ,读取不到hive元数据问题
    Hadoop之HDFS(二)HDFS工作机制和集群安全模式
    Spark中的Driver和Executor详解及相关调优
    Linux查看物理CPU个数、核数、逻辑CPU个数
    shell命令查看进程id,并杀死进程,停止脚本
    Flink CDC 2.0 正式发布,详解核心改进
    Kafka 如何保证消息的消费顺序一致性
  • 原文地址:https://www.cnblogs.com/z520h123/p/9932316.html
Copyright © 2011-2022 走看看