<笔记>第三篇:面向对象(一)

  • 目的:开发一款叫做<人狗大战>的游戏
    • def person(name,age,sex,job):
          data = {
              'name':name,
              'age':age,
              'sex':sex,
              'job':job
          }
       
          return data
       
      def dog(name,dog_type):
          data = {
              'name':name,
              'type':dog_type
          }
          return data
  • 上面代码相当于造了2个模子,根据这两个模子塑造具体的人或者狗
    • d1 = dog("李磊","京巴")
      p1 = person("严帅",36,"F","运维")
      p2 = person("egon",27,"F","Teacher")
  • 为了实现狗和人不同的功能 

    • 版本V1.0:需要的功能重新写函数,在让这两个对象去调用  

      • def bark(d):
            print("dog %s:wang.wang..wang..."%d['name'])
         
         
        def walk(p):
            print("person %s is walking..." %p['name'])<br><br>
        
        walk(p1) 
        bark(d1)
    • 版本2.0:限制人调用狗的功能,狗调用人的功能  

      • def person(name,age,sex,job):
            def walk(p):
                print("person %s is walking..." % p['name'])
         
            data = {
                'name':name,
                'age':age,
                'sex':sex,
                'job':job,
                'walk':walk
            }
         
            return data
         
        def dog(name,dog_type):
         
         
            def bark(d):
                print("dog %s:wang.wang..wang..."%d['name'])
            data = {
                'name':name,
                'type':dog_type,
                'bark':bark
            }
         
            return data
        
        d1 = dog("李磊","京巴")
        p1 = person("严帅",36,"F","运维")
        p2 = person("egon",27,"F","Teacher")
    • 这种编程思想就是简单的面向对象的编程

  • 面向过程和面向对象

    • 面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。 

      • 优缺点

        • 优点:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。

        • 缺点:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。   

      • 应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等 

    • 面向对象的程序设计的核心是对象(上帝式思维),要理解对象为何物,必须把自己当成上帝,上帝眼里世间存在的万物皆为对象,不存在的也可以创造出来。

      • 每个对象都有自己的特征和技能,特征和技能分别对应对象的属性和方法

      • 优缺点

        • 优点:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。  

        • 缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果 于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现,一刀砍死3个人,这个游戏就失去平衡。

      • 应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方。  

      • 面向对象编程使程序的维护和扩展变得简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。

      • 一些名词:类、对象、实例、实例化

        • 类:具有相同特征的一类事物(人、狗、老虎)  

        • 对象/实例:具体的某一个事物(隔壁阿花、楼下旺财)   

        • 实例化:类——>对象的过程(这在生活中表现的不明显,我们在后面再慢慢解释)    

    • 什么是类?类就相当于制造飞机时的图纸,用它来进行创建的飞机就相当于对象
      • 其实在前面我们已经使用很长时间的类了,比如:
        • >>> dict #类型dict就是类dict
          <class 'dict'>
          >>> d=dict(name='eva') #实例化
          >>> d.pop('name') #向d发一条消息,执行d的方法pop
          'eva'
      • 在python中,用变量表示特征,用函数表示技能,因而具有相同特征和技能的一类事物就是‘类’,对象是则是这一类事物中具体的一个。
    • 类的设计举例:
      • 1)人类设计,只关心3样东西:
        
          事物名称(类名):人(Person)
          属性:身高(height)、年龄(age)
          方法(行为/功能):跑(run)、打架(fight)
        2)狗类的设计
          类名:狗(Dog)
          属性:品种 、毛色、性别、名字、 腿儿的数量
          方法(行为/功能):叫 、跑、咬人、吃、摇尾巴
    • 创建类的模板
      • class Person:   #定义一个人类
            role = 'person'  #人的角色属性都是人
        def walk(self): #人都可以走路,也就是有一个走路方法,也叫动态属性 print("person is walking...")
    • 类有两种作用:属性引用和实例化

      • 属性引用(类名.属性)
        Person.role  #查看人的role属性
        Person.walk  #引用人的走路方法,注意,这里不是在调用
    • 实例化的过程:类——>对象的过程     就是通过图纸造出具体的东西

      • 语法:对象名 = 类名(参数)

      • egg = Person('egon')  #类名()就等于在执行Person.__init__()
        #执行完__init__()就会返回一个对象。这个对象类似一个字典,存着属于这个人本身的一些属性和方法。
    • 查看属性&调用方法

      • print(egg.name)     #查看属性直接 对象名.属性名
        print(egg.walk())   #调用方法,对象名.方法名()
    • self:实例化时自动将对象/实例本身传给__init__的第一个参数。某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面的参数即可

    • 类属性补充

      • 一:我们定义的类的属性到底存到哪里了?有两种方式查看
        dir(类名):查出的是一个名字列表
        类名.__dict__:查出的是一个字典,key为属性名,value为属性值
        
        二:特殊的类属性
        类名.__name__# 类的名字(字符串)
        类名.__doc__# 类的文档字符串
        类名.__base__# 类的第一个父类(在讲继承时会讲)
        类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
        类名.__dict__# 类的字典属性
        类名.__module__# 类定义所在的模块
        类名.__class__# 实例对应的类(仅新式类中)
    • 给人狗大战增加技能

      • class Person:  # 定义一个人类
            role = 'person'  # 人的角色属性都是人
        
            def __init__(self, name, aggressivity, life_value):
                self.name = name  # 每一个角色都有自己的昵称;
                self.aggressivity = aggressivity  # 每一个角色都有自己的攻击力;
                self.life_value = life_value  # 每一个角色都有自己的生命值;
        
            def attack(self,dog):  
                # 人可以攻击狗,这里的狗也是一个对象。
                # 人攻击狗,那么狗的生命值就会根据人的攻击力而下降
                dog.life_value -= self.aggressivity
        
        
        对象是关于类而实际存在的一个例子,即实例
        对象/实例只有一种作用:属性引用
        egg = Person('egon',10,1000)
        print(egg.name)
        print(egg.aggressivity)
        print(egg.life_value)
        print(egg.attack)
    • 利用函数理解类

      • def Person(*args,**kwargs):
            self = {}
            def attack(self,dog):
                dog['life_value'] -= self['aggressivity']
        
            def __init__(name,aggressivity,life_value):
                self['name'] = name
                self['aggressivity'] = aggressivity
                self['life_value'] = life_value
                self['attack'] = attack
        
            __init__(*args,**kwargs)
            return self
        
        egg = Person('egon',78,10)
        print(egg['name'])
    • 类的定义和调用模板

      • class 类名:
            def __init__(self,参数1,参数2):
                self.对象的属性1 = 参数1
                self.对象的属性2 = 参数2
        
            def 方法名(self):pass
        
            def 方法名2(self):pass
        
        对象名 = 类名(1,2)  #对象就是实例,代表一个具体的东西
                          #类名() : 类名+括号就是实例化一个类,相当于调用了__init__方法
                          #括号里传参数,参数不需要传self,其他与init中的形参一一对应
                          #结果返回一个对象
        对象名.对象的属性1   #查看对象的属性,直接用 对象名.属性名 即可
        对象名.方法名()     #调用类中的方法,直接用 对象名.方法名() 即可
    • 对象之间的交互

      • class Dog:  # 定义一个狗类
            role = 'dog'  # 狗的角色属性都是狗
        
            def __init__(self, name, breed, aggressivity, life_value):
                self.name = name  # 每一只狗都有自己的昵称;
                self.breed = breed  # 每一只狗都有自己的品种;
                self.aggressivity = aggressivity  # 每一只狗都有自己的攻击力;
                self.life_value = life_value  # 每一只狗都有自己的生命值;
        
            def bite(self,people):
                # 狗可以咬人,这里的狗也是一个对象。
                # 狗咬人,那么人的生命值就会根据狗的攻击力而下降     
        	dog.life_value -= self.aggressivit
        
        
        实例化一只狗
        
        ha2 = Dog('二愣子','哈士奇',10,1000)  #创造了一只实实在在的狗ha2
        
        
        print(ha2.life_value)         #看看ha2的生命值
        egg.attack(ha2)               #egg打了ha2一下
        print(ha2.life_value)         #ha2掉了10点血
    • 理解面向对象

      • from math import pi
        
        class Circle:
            '''
            定义了一个圆形类;
            提供计算面积(area)和周长(perimeter)的方法
            '''
            def __init__(self,radius):
                self.radius = radius
        
            def area(self):
                 return pi * self.radius * self.radius
        
            def perimeter(self):
                return 2 * pi *self.radius
        
        
        circle =  Circle(10) #实例化一个圆
        area1 = circle.area() #计算圆面积
        per1 = circle.perimeter() #计算圆周长
        print(area1,per1) #打印圆面积和周长
    • 当使用print输出对象的时候,只要自己定义了__str__(self)方法,那么就会打印从在这个方法中return的数据

      •     def __str__(self):
                msg = "嘿。。。我的颜色是" + self.color + "我有" + int(self.wheelNum) + "个轮胎..."
                return msg
    • 烤地瓜代码

      • class SweetPotato:
            "这是烤地瓜的类"
        
            #定义初始化方法
            def __init__(self):
                self.cookedLevel = 0
                self.cookedString = "生的"
                self.condiments = []
        
            #定制print时的显示内容
            def __str__(self):
                msg = self.cookedString + " 地瓜"
                if len(self.condiments) > 0:
                    msg = msg + "("
        
                    for temp in self.condiments:
                        msg = msg + temp + ", "
                    msg = msg.strip(", ")
        
                    msg = msg + ")"
                return msg
        
            #烤地瓜方法
            def cook(self, time):
                self.cookedLevel += time
                if self.cookedLevel > 8:
                    self.cookedString = "烤成灰了"
                elif self.cookedLevel > 5:
                    self.cookedString = "烤好了"    
                elif self.cookedLevel > 3:
                    self.cookedString = "半生不熟"
                else:
                    self.cookedString = "生的"
        
            #添加配料
            def addCondiments(self, condiments):
                self.condiments.append(condiments)
        
        # 用来进行测试
        mySweetPotato = SweetPotato()
        print("------有了一个地瓜,还没有烤-----")
        print(mySweetPotato.cookedLevel)
        print(mySweetPotato.cookedString)
        print(mySweetPotato.condiments)
        print("------接下来要进行烤地瓜了-----")
        print("------地瓜经烤了4分钟-----")
        mySweetPotato.cook(4) #烤4分钟
        print(mySweetPotato)
        print("------地瓜又经烤了3分钟-----")
        mySweetPotato.cook(3) #又烤了3分钟
        print(mySweetPotato)
        print("------接下来要添加配料-番茄酱------")
        mySweetPotato.addCondiments("番茄酱")
        print(mySweetPotato)
        print("------地瓜又经烤了5分钟-----")
        mySweetPotato.cook(5) #又烤了5分钟
        print(mySweetPotato)
        print("------接下来要添加配料-芥末酱------")
        mySweetPotato.addCondiments("芥末酱")
        print(mySweetPotato)
    • 存放家具代码

      • #定义一个home类
        class Home:
        
            def __init__(self, area):
                self.area = area #房间剩余的可用面积
                #self.light = 'on' #灯默认是亮的
                self.containsItem = []
        
            def __str__(self):
                msg = "当前房间可用面积为:" + str(self.area)
                if len(self.containsItem) > 0:
                    msg = msg + " 容纳的物品有: "
                    for temp in self.containsItem:
                        msg = msg + temp.getName() + ", "
                    msg = msg.strip(", ")
                return msg
        
            #容纳物品
            def accommodateItem(self,item):
                #如果可用面积大于物品的占用面积
                needArea = item.getUsedArea()
                if self.area > needArea:
                    self.containsItem.append(item)
                    self.area -= needArea
                    print("ok:已经存放到房间中")
                else:
                    print("err:房间可用面积为:%d,但是当前要存放的物品需要的面积为%d"%(self.area, needArea))
        
        
        #定义bed类
        class Bed:
        
            def __init__(self,area,name = '床'):
                self.name = name
                self.area = area
        
            def __str__(self):
                msg = '床的面积为:' + str(self.area)
                return msg
        
            #获取床的占用面积
            def getUsedArea(self):
                return self.area
        
            def getName(self):
                return self.name
        
        
        #创建一个新家对象
        newHome = Home(100)#100平米
        print(newHome)
        
        #创建一个床对象
        newBed = Bed(20)
        print(newBed)
        
        #把床安放到家里
        newHome.accommodateItem(newBed)
        print(newHome)
        
        #创建一个床对象
        newBed2 = Bed(30,'席梦思')
        print(newBed2)
        
        #把床安放到家里
        newHome.accommodateItem(newBed2)
        print(newHome)
        

          

                                      

                         

           

          

                            
posted @ 2020-09-09 16:48  水墨黑  阅读(152)  评论(0编辑  收藏  举报