zoukankan      html  css  js  c++  java
  • 面向对象

    面向对象

    一.面向对象初识

    1. 函数式编程的优点
      • 减少代码的重复性
      • 增强代码的可读性
    2. 函数式编程vs面向对象编程
    3. 面向对象编程的优点

      • 是一类相似功能函数的集合,使代码更清晰化,更合理化
      • 面向对象,要拥有上帝视角看问题,类其实就是一个公共模板,对象就从具体的模板实例化出来
    4. 类的结构
      class Human:
          '''
          此类主要构建人类
          '''
          mind = '有思想'    # 第一部分:静态属性 属性 静态变量 静态字段
          dic = {}
          l1 = []
          def work(self):    # 第二部分 : 方法 函数 动态属性
              print('人类社会工作')
      # class 是关键字与def用法相同,定义一个类
      # Human 是此类的类名,类名使用驼峰(CamelCase)命名风格,首字母大写,私有类可用一个下划线开头
      # 类的结构从大方向来说就分为两部分:
      # 静态变量
      # 动态方法
      

    二,从类名的角度研究类

    1. 类名操作静态属性
      # 第一种:查看类中的所有内容: 类名.__dict__方式
      class Human:
          mind = '有思想' 
          dic = {}
          l1 = []
          def work(self): 
              print('人类会工作')
      
      print(Human.__dict__) # 查看所有内容
      print(Human.__dict__['mind']) 
      Human.__dict__['mind'] = '无脑' # 报错
      print(Human.__dict__)  
      # 通过这种方式只能查询,不能增删改.一般只用于查询全部内容(一般不用单独属性查询)
      -------------------------------------------------------
      # 第二种: 万能的点
      print(Human.mind)  # 查
      Human.mind = '无脑'  # 改
      print(Human.mind)
      del Human.mind  # 删
      Human.walk = '直立行走'  # 增
      print(Human.walk)
      # 通过万能的点 可以增删改查类中的单个属性
      

      总结: 如果想要查询类中所有的内容,通过类名.__dict__方法,如果只是操作单个属性,则用万能的点的方式

    2. 类名操作动态方法
      # 除了两个特殊的方法: 静态方法,类方法之外,一般不会通过类名操作一个类中的方法
      class Human:
          mind = '有思想' 
          dic = {}
          l1 = []
          def work(self): 
              print('人类会工作')
          def tools(self):
          	print('人类会使用工具')
          	
      Human.work(111)
      Human.tools(111)
      # 下面可以做,但不用。
      Human.__dict__['work'](111)
      

    三,从对象的角度研究类

    1. 什么是对象?
      • 对象是从类中出来的,只要是类名加上(),这就是一个实例化的过程,这个就会实例化一个对象

        class Human:
            mind = '有思想'
            def __init__(self):
                print(666)
                print(self)  # <__main__.Human object at 0x00000191508AA828>
        
            def work(self): 
                print('人类会工作')
        
            def tools(self):
                print('人类会使用工具')
        obj = Human() # 只要实例化对象,它会自动执行__init__方法
        print(obj)  # <__main__.Human object at 0x00000191508AA828>
        # 并且obj的地址与self的地址相同
        

        实例化一个对象会发生的三件事:

        1. 在内存中会开辟一个对象空间

        2. 自动执行类中的__init__方法,并将这个对象空间(内存地址)传给了__init__方法的第一个位置参数self

        3. __init__方法中通过self给对象空间封装属性

          class Human:
              mind = '有思想'
              language = '使用语言'
              def __init__(self,name,sex,age,hobby):
                  # self 和 obj 指向的是同一个内存地址同一个空间,下面就是通过self给这个对象空间封装四个属性。
                  self.n = name
                  self.s = sex
                  self.a = age
                  self.h = hobby
          
          obj = Human('barry','男',18,'运动')
          
    2. 对象操作对象空间属性
      # 对象查询对象中所有属性: 对象.__dict__
      print(obj.__dict__)  # {'n': 'barry', 'h': '运动', 's': '男', 'a': 18}
      # 对象操作对象中的单个属性: 万能的点.
      obj.job = 'IT'  # 增
      del obj.n  # 删
      obj.s = '女' # 改
      print(obj.s)  # 查
      print(obj.__dict__)
      
    3. 对象查看类中的属性
      class Human:
          mind = '有思想'
          language = '实用语言'
          def __init__(self,name,sex,age,hobby):
              self.n = name
              self.s = sex
              self.a = age
              self.h = hobby
      
      obj = Human('barry','男',18,'运动')
      print(obj.mind)
      print(obj.language)
      obj.a = 666
      print(obj.a)
      
    4. 对象操作类中的方法
      class Human:
          mind = '有思想'
          language = '实用语言'
          def __init__(self,name,sex,age,hobby):
              self.n = name
              self.s = sex
              self.a = age
              self.h = hobby
      
          def work(self):
              print(self)
              print('人类会工作')
      
          def tools(self):
              print('人类会使用工具')
      
      obj = Human('barry','男',18,'运动')
      obj.work()
      obj.tools()
      

      类中的方法一般都是通过对象执行的(除去类方法,静态方法外),并且对象执行这些方法都会自动将空间传给方法中的第一个参数self

    5. self是什么

      self其实就是类中方法(函数)的第一个位置参数,只不过解释器会自动将调用这个函数的对象传给self,所以咱们把类中的方法的第一个参数约定俗成设置成self,代表这个就是对象,一个类可以实例化多个对象
    6. 一个类可以实例化多个对象
      obj1= Human('小胖','男',20,'美女')
      obj2= Human('小马','女',18,'帅哥')
      print(obj1,obj2)
      print(obj1.__dict__)   #对象查看对象空间的属性
      print(obj2.__dict__)
      

    四.类的空间问题

    1. 何处可以添加对象属性
      class A:
          def __init__(self, name):
              self.name = name
      
          def func(self, sex):
              self.sex = sex
      
      # 类外面可以
      obj = A('太上老君')
      obj.age = 18
      print(obj.__dict__)  # {'name': '太上老君', 'age': 18}
      
      # 类内部也可以
      obj = A('元始天尊') # __init__方法可以
      obj.func('男')      # func 方法也可以
      print(obj.__dict__) # {'name': '元始天尊', 'sex': '男'}
      
      • 总结: 对象的属性不仅可以在__init__里面添加,还可以在类的其他地方或者类的外面添加
    2. 何处可以添加类的静态属性
      class A:
          def __init__(self, name):
              self.name = name
          def func(self, sex):
              self.sex = sex
      
          def func1(self):
              A.bbb = 'ccc'
      
      # 类的外部可以添加
      A.aaa = 'dsb'
      print(A.__dict__)
      
      # 类的内部也可以添加
      A.func1(111)  	# 这个111只是为了不报错
      print(A.__dict__)
      
      • 总结: 类的属性不仅可以在类内部添加,还可以在类的外部添加
    3. 对象和类查找属性的顺序
      • 对象之所以可以找到类,是因为在对象空间里有类对象指针这么个东西

      • 对象查找属性的顺序

        对象空间--->类空间------>父类空间

      • 类名查找属性的顺序

        本类空间--->父类空间

      • 查找顺序是单向不可逆的,类名不可能找到对象的属性

    五,类与类之间的关系

    1. 依赖关系:
      • 将一个类的对象或类名传到另一个类的方法使用,这两个类就是依赖关系,依赖关系还是通过原对象.的方式调用方法
        # 大象进冰箱
        class Elephant:
            def __init__(self, name):
                self.name = name
        
            def open_(self, self2): # self2 == bingxiang
                print(f'{self.name}大象打开冰箱门')
                self2.open_door() # 依赖关系还是通过原对象.的方式调用方法
        
            def close_(self, self2):
                print(f'{self.name}大象关上冰箱门')
                self2.close_door()
        
        class Refrigerator:
            def __init__(self, name):
                self.name = name
        
            def open_door(self):  
                print(f'{self.name}冰箱门被打开了')
            def close_door(self):
                print(f'{self.name}冰箱门被关上了')
        
        daxiang = Elephant('奇奇')
        bingxiang = Refrigerator('格力')
        daxiang.open_(bingxiang)
        daxiang.close_(bingxiang)
        # 奇奇大象打开冰箱门
        # 格力冰箱门被打开了
        # 奇奇大象关上冰箱门
        # 格力冰箱门被关上了
        
    2. 关联,聚合,组合关系(在python中统一叫做组合关系)
      • 组合关系:将一个类的对象封装到另一个类的的对象的属性中,就叫做组合
        # 男孩的女朋友
        class Boy:
            def __init__(self, name, girlfriend=None):
                self.name = name
                self.girlfriend = girlfriend  # 将另一个对象作为属性,封装到本对象中
            def have_a_diner(self):
                if self.girlfriend:
                    print(f'{self.name}和{self.girlfriend.name}一起吃晚饭.')
                    self.girlfriend.shopping(self) # 组合关系是以当前对象为主体调用另一个对象的方法
                else:
                    print('单身狗,吃什么饭.')
        
        class Girl:
            def __init__(self, name):
                self.name = name
            def shopping(self, self2):
                print(f'{self.name}和{self2.name}一起去购物')
        b = Boy('小明')
        b.have_a_diner() # 此时单身狗
        
        g = Girl('小丽')
        b.girlfriend = g # 有了女朋友
        b.have_a_diner()
        
        gg = Girl('小花')
        bb = Boy('小李', gg)
        bb.have_a_diner()
        
        bb.girlfriend = None  # 分手了
        bb.have_a_diner()
        
        # 学校和老师
        class School:
            def __init__(self, name, address):
                self.name = name
                self.address = address
        
        class Teacher:
            def __init__(self, name, school):
                self.name = name
                self.school = school
        
        s1 = School('北京大学', '喧哗的北京')
        s2 = School('浙江大学', '美丽的浙江')
        s3 = School('武汉大学', '美女如云的武汉')
        
        t1 = Teacher('王健林', s1)
        t2 = Teacher('马云', s2)
        t3 = Teacher('董明珠', s3)
        
        print(t1.school.name)
        print(t2.school.name)
        print(t3.school.name)
        北京大学
        浙江大学
        武汉大学
        
        # 设计一个游戏人物类,实例化几个对象让这几个游戏人物实现互殴的效果
        class Gamerole:
            def __init__(self, name, ad, hp):
                self.name = name
                self.ad = ad
                self.hp = hp
            def attack(self, p1):
                p1.hp -= self.ad
                print(f'{self.name}攻击了{p1.name},{p1.name}掉了{self.ad}血,还剩{p1.hp}血')
        
        # 再写个武器类
        class Weapon:
            def __init__(self, name, ad):
                self.name = name
                self.ad = ad
            def weapon_attack(self, p1, p2):
                p2.hp = p2.hp - p1.ad - self.ad
                print(f'{p1.name}利用{self.name}攻击了{p2.name},{p2.name}还剩{p2.hp}血')
                
        gailun = Gamerole('德玛西亚之力', 10, 200)
        yasuo = Gamerole('疾风剑豪', 20, 80)
        dabaojian = Weapon('大宝剑', 20)
        dabaojian.weapon_attack(gailun, yasuo)
        
        # 但是这样不好,利用武器攻击也是人类是动作的发起者,所以不能是dabaojian对象发起
        ------------------修改后如下------------------
        # 修改代码
        class Gamerole:
            def __init__(self, name, ad, hp):
                self.name = name
                self.ad = ad
                self.hp = hp
            def attack(self, p1):
                p1.hp -= self.ad
                print(f'{self.name}攻击了{p1.name},{p1.name}掉了{self.ad}血,还剩{p1.hp}血')
            def equip_weapon(self, wea): # 组合,给一个对象封装一个属性,该属性是另一个类的对象
                self.wea = wea
        
        class Weapon:
            def __init__(self, name, ad):
                self.name = name
                self.ad = ad
            def weapon_attack(self, p1, p2):
                p2.hp = p2.hp - p1.ad - self.ad
                print(f'{p1.name}利用{self.name}攻击了{p2.name},{p2.name}还剩{p2.hp}血')
        
        # 实例化2个人物,1个武器
        gailun = Gamerole('德玛西亚之力', 10, 200)
        yasuo = Gamerole('疾风剑豪', 20, 80)
        dabaojian = Weapon('大宝剑', 20)
        
        # 给人物装备上武器对象
        gailun.equip_weapon(dabaojian)
        
        # 开始攻击
        gailun.wea.weapon_attack(gailun, yasuo) # 攻击是以盖伦为主体的
        
  • 相关阅读:
    CodeForces 219D Choosing Capital for Treeland (树形DP)
    POJ 3162 Walking Race (树的直径,单调队列)
    POJ 2152 Fire (树形DP,经典)
    POJ 1741 Tree (树的分治,树的重心)
    POJ 1655 Balancing Act (树的重心,常规)
    HDU 2196 Computer (树形DP)
    HDU 1520 Anniversary party (树形DP,入门)
    寒门子弟
    JQuery选择器(转)
    (四)Web应用开发---系统架构图
  • 原文地址:https://www.cnblogs.com/maqian/p/11940426.html
Copyright © 2011-2022 走看看