面向对象的编程思想、类与对象、对象的实例化

今日学习内容总结

      经过昨天对项目的练习,我们已经对之前学习的知识进行了一个整合的体验,因为整个项目中的代码与逻辑,其实都是之前学习过的知识。这个项目的完成程度,就是你对之前学习一个总结的程度。灵活运用,以及对编程思想的转变是必不可少的。而今天我们将会再一次的对编程思想进行理解,学习内容就是面向对象。

面向对象的编程思想

      在提出什么是面向对象的编程思想之前,我们先体会一下面向对象的前戏:

      比如一个简单的狗咬人,人打狗的一个简单的游戏。那么我们至少需要两个角色,那就是人,和狗的。并且因为他们会互相攻击,所以他们都应该有攻击力,有生命值。同时,他们有不同的名称,性别等。那么怎么去描述这种不同的角色和他们的功能。于是就有了下面这样的一个推导过程:

  # 描述人和狗  我们用字典描述
   person1 = {
       'name': 'jason',
       'type': '猛男',
       'attack_val': 100,
       'life_val': 1000
   }

   dog2 = {
       'name': '匕首狗',
       'type': '泰迪',
       'attack_val': 50,
       'life_val': 300
   }

  # 用这种方法虽然能描述,但是每出现新的角色都要这么写,代码冗余量会很大,所以封装成函数
   def get_person(name, gender, age, t_type, attack_val, life_val):
       data_dict = {
           'name': name,
           'gender': gender,
           'age': age,
           't_type': t_type,
           'attack_val': attack_val,
           'life_val': life_val
       }
       return data_dict
   def get_dog(name, t_type, attack_val, life_val):
       data_dict = {
           'name': name,
           't_type': t_type,
           'attack_val': attack_val,
           'life_val': life_val
       }
       return data_dict

  # 通过函数,就能创建不同的角色了。
  p1 = get_person('jason', 'male', 18, '猛男', 800, 1000)
  dog1 = get_dog('小黑', '松狮犬', 300, 500)

  # 既然是狗咬人,人打狗的游戏,我们就用最简单的掉血逻辑完成
  def dog_attack(dog_obj, person_obj):
      """
      :param dog_obj: 接收一条狗
      :param person_obj: 接收一个人
      """
      # 人的血量减去狗的攻击力
      print('当前人的血量是:%s' % person_obj.get('life_val'))
      person_obj['life_val'] -= dog_obj.get('attack_val')
      print("""狗:%s 咬了人:%s 一口 人掉血:%s 剩余血量:%s""" `%(dog_obj.get('name'),person_obj.get('name'),dog_obj.get('attack_val'),person_obj['life_val']))
  
  def person_attack(person_obj, dog_obj):
      """
      :param person_obj: 接收一个人
      :param dog_obj: 接收一条狗
      """
      print('当前狗的血量是:%s'%dog_obj.get('life_val'))
      dog_obj['life_val'] -= person_obj.get('attack_val')
      print("""人:%s 锤了狗:%s 一下 狗掉血:%s 剩余血量:%s"""%(person_obj.get('name'),dog_obj.get('name'),person_obj.get('attack_val'),dog_obj['life_val']))

  # 通过这种方式,我们就简单的实现了这个小游戏。但是在实际调用的时候
  dog_attack(dog2,p1)
  print(p1)
  # 人锤狗
  person_attack(p2, dog1)
  print(dog1)
  '''人调用了狗的攻击动作'''
  # dog_attack(p1, dog1)
  '''狗调用了人的攻击工作'''
  # person_attack(dog2,p2)

  # 所以我们为了避免这种情况出现,让人的数据跟人的功能绑定,狗的数据跟狗的功能绑定
  def get_person(name, gender, age, t_type, attack_val, life_val):
    # 将人的攻击动作放在产生人的函数内
    def person_attack(person_obj, dog_obj):
        """
        :param person_obj: 接收一个人
        :param dog_obj: 接收一条狗
        """
        print('当前狗的血量是:%s' % dog_obj.get('life_val'))
        dog_obj['life_val'] -= person_obj.get('attack_val')
        print("""人:%s 锤了狗:%s 一下 狗掉血:%s 剩余血量:%s""" % (
        person_obj.get('name'), dog_obj.get('name'), person_obj.get('attack_val'), dog_obj['life_val']))

    data_dict = {
        'name': name,
        'gender': gender,
        'age': age,
        't_type': t_type,
        'attack_val': attack_val,
        'life_val': life_val,
        'person_attack':person_attack
    }
    return data_dict
  def get_dog(name, t_type, attack_val, life_val):
    def dog_attack(dog_obj, person_obj):
        """
        :param dog_obj: 接收一条狗
        :param person_obj: 接收一个人
        """
        # 使用最简答的掉血逻辑  血量减去对方攻击力
        print('当前人的血量是:%s' % person_obj.get('life_val'))
        person_obj['life_val'] -= dog_obj.get('attack_val')
        print("""狗:%s 咬了人:%s 一口 人掉血:%s 剩余血量:%s""" % (
        dog_obj.get('name'), person_obj.get('name'), dog_obj.get('attack_val'), person_obj['life_val']))
    data_dict = {
        'name': name,
        't_type': t_type,
        'attack_val': attack_val,
        'life_val': life_val,
        'dog_attack':dog_attack
    }
    return data_dict

  # 上述操作其实就是将数据与功能进行绑定,不再是所有的数据都可以调用任意的功能

      通过上述代码的将数据与功能整合到一起的操作其实就是面向对象编程的思想。

      面向过程编程:将程序的执行流程化,即分步操作,分步的过程中解决问题。对于面向过程的思想: 需要实现一个功能的时候,看重的是开发的步骤和过程,每一个步骤都需要自己亲力亲为,需要自己编写代码(自己来做)。过程可以理解成是流水线,面向过程编程可以理解成是在创建一条流水线。

      面向对象编程:核心就是'对象'二字,对象其实就是一个"容器" 将数据与功能整合到一起,只要是符合上述描述的事物都可以称之为是对象。对于面向对象的思想:当需要实现一个功能的时候,看重的并不是过程和步骤,而是关心谁帮我做这件事(偷懒,找人帮我做)。python针对面向对象编程提供了专门的语法,识别度更高,编写更精简。

      仔细想想会发现,python中一切皆对象,面向过程与面向对象两者没有优劣之分,具体要结合实际情况,甚至很多时候两者是混合在一起的,思想占据的比例不同而已。

类与对象

      对象:数据与功能的结合体。类:即类别、种类。相当于诸多对象公有的特征(数据、功能)。举一个简单的例子,一个人,叫人。同时也是一个对象。但是一群人,成为人类。每个人是不同的,但是每个人都有共同的部分,称之为人的部分。这就体现出了类和对象的区别。从描述中我们发现,其实类也是对象。所以一切皆对象。

      在代码层面,其实是先有类才能有对象的。

  # 先定义类 后产生对象
  # 学生类
  class Student:
      # 学生类公共的数据
      school = '清华大学'
      # 学生类公共的功能
      def choose_course(self):
          print('学生选课功能')
  """类体代码无需调用就会执行 产生类的名称空间"""

      语法结构:

'''
  class 类名:
      类体代码
  1.class是定义类的关键字
  2.类名类似于函数名 但是首字母推荐大写 用于区分
  3.类体代码就是存放对象公共数据和功能的地方
      数据: 变量名 = 变量值
      功能: 函数
'''
  查看名称空间的方法>>>:__dict__
  print(Student.__dict__)  # 返回值是一个字典
  print(Student.__dict__['school'])  # 获取类中的属性
  print(Student.__dict__['choose_course'])  # 获取类中的属性
  # 类获取数据和功能有一个简便的方式>>>:句点符
  print(Student.school)
  print(Student.choose_course)

      产生对象的方法:类名加括号:

  obj1 = Student()  # 类名加括号就是在产生一个对象
  obj2 = Student()
  print(obj1.__dict__, obj2.__dict__)  # {} {}
  print(obj1.school)  # 清华大学
  print(obj2.school)  # 清华大学
  print(obj1.choose_course)  # bound method
  print(obj2.choose_course)  # bound method
  print(obj1.school)  # 清华大学
  print(obj2.school)  # 清华大学
  Student.school = '北京大学'  # Student.__dict__['school'] = '北京大学'  修改名字与值的对应关系
  print(obj1.school)  # 北京大学
  print(obj2.school)  # 北京大学

对象的实例化

      在类中__init__()函数叫构造函数,又叫构造方法,也可以叫初始化函数。它的作用就是初始化实例时,初始化传入实例的的默认值。如果不写__init__(),就会调用的默认为空的__init__(),说白了,这个方法不管你写不写,都会调用,而且,一旦实例化就会调用。

      类产生对象的具体步骤:

'''
    1.先创建一个没有独有数据的空对象  {}
    2.将空对象和类括号内传入的数据一并交给__init__执行
        __init__的第一个参数就是对象本身
            __init__(obj,name,age,gender)
    3.将创建好的对象自动返回
'''

      代码示例:

  class Student:
      def __init__(self, name, age, gender):
          '''该方法就一个功能>>>:给对象添加独有的数据'''
          self.name = name  # obj.__dict__['name'] = name
          self.age = age  # obj.__dict__['age'] = age
          self.gender = gender  # obj.__dict__['gender'] = gender

      # 学生类公共的数据
      school = '清华大学'

      # 学生类公共的功能
      def choose_course(self):
          print('学生选课功能')

  # 类中针对给对象创建独有数据的函数名,专门定义了一个固定的方法
  obj1 = Student('jason', 18, 'male')
  obj2 = Student('kevin', 28, 'female')
  print(obj1.__dict__)
  print(obj2.__dict__)

  # 针对括号内第一个形参self其实就是一个普通的变量名而已,只不过该变量名将来专门接收对象的,所以给它起了个固定的名字叫self

      绑定方法:

      在类中定义的函数默认都是绑定给对象使用的,就是对象来调,会自动将对象当做第一个参数传入。

  class Student:
      school = '清华大学'
      # __init__方法不要自己去调用 
      def __init__(self, name, age):
          self.name = name
          self.age = age

      def func(self):
          print('%s正在调用func方法'%self.name)

      def index(self):
          print('%s正在调用index方法'%self.name)

  obj1 = Student('jason', 18)
  print(obj1)
  obj2 = Student('kevin', 28)
  # 类调用类中函数 有几个参数就需要传几个参数
  Student.func(123,222)
  # 对象调用类中函数  会将当前调用的对象当做第一个参数自动传入
  obj1.func()
  obj2.func()
  print(obj1.func)
  print(obj2.index)

  # 这样就能理解为什么类中所有的函数第一个参数都是self
posted @ 2022-04-06 21:51  くうはくの白  阅读(70)  评论(0)    收藏  举报