• 面向对象


    面向对象

    一.面向对象初识

    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) # 攻击是以盖伦为主体的
        
  • 相关阅读:
    Unity3d 4.3 通过代码动态更改SpriteRender的Sprite
    使用Unity3D的50个技巧:Unity3D最佳实践
    仿照wtform自定义Form组件
    flask-script
    Django中的信号
    浅淡python中with的用法,上下文管理器
    类和对象的创建过程(元类,__new__,__init__,__call__)
    flask-wtforms
    flask-session组件
    Flask-信号(blinker)
  • 原文地址:https://www.cnblogs.com/maqian/p/11940426.html
Copyright © 2020-2023  润新知