面对对象初识

【一】人狗大战小游戏引入

【1】游戏规则分析

  • 人可以打狗,狗掉血,狗可以咬人,人掉血

  • 人的属性

    • 姓名

    • 类型

    • 年龄

    • 攻击力

    • 生命值

  • 狗的属性

    • 姓名

    • 类型

    • 年龄

    • 攻击力

    • 生命值

【二】封装成函数,减少代码冗余

复制代码
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
​
​
p1 = get_person('knight', 'male', 22, '猛男', 50, 1000)
p2 = get_person('ddt', 'female', 24, '淑女', 10, 100)
dog1 = get_dog('小黑', '松狮犬', 30, 500)
dog2 = get_dog('小白', '泰迪犬', 10, 200)
p1['person_attack'](p1, dog1)
dog1['dog_attack'](dog1, p2)

(二)什么是面对对象

【1】面向对象理解

  • 面向对象就相当于上帝,在上帝的视角,人是对象,动物是对象,石头是对象,水是对象,山是对象.....存在的可以扩充,不存在的可以创造。

【2】面向对象的优缺点

(1)面对对象的优点
  • 解决程序的延展性

  • 对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。

(2)面向对象的缺点
  • 编程的复杂度远高于面向过程,不了解面向对象而立即上手基于它设计程序,极容易出现过度设计的问题。

    • 一些扩展性要求低的场景使用面向对象会徒增编程难度,比如管理linux系统的shell脚本就不适合用面向对象去设计,面向过程反而更加适合。
  • 无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法准确地预测最终结果。

    • 于是我们经常看到对战类游戏,新增一个游戏人物,在对战的过程中极容易出现阴霸的技能,一刀砍死3个人,这种情况是无法准确预知的,只有对象之间交互才能准确地知道最终的结果。

【3】什么是程序

  • 程序=数据+功能

  • 编写程序的本质就是定义一系列的数据,然后写出一些功能对数据进行操作

【三】类与对象

【1】什么是类

  • 类即类别、种类,是面向对象设计最重要的概念,对象是特征与技能的结合体,而类则是一系列对象相似的特征与技能的结合体

  • 所以,先有鸡和先有蛋的问题就出来了

    • 先有的一个个具体存在的对象(比如一个具体存在的人)

    • 还是先有的人类这个概念,这个问题需要分两种情况去看

(1)现实中
  • 在现实世界中:先有对象,再有类

  • 世界上肯定是先出现各种各样的实际存在的物体,然后随着人类文明的发展,人类站在不同的角度总结出了不同的种类,如人类、动物类、植物类等概念

  • 也就说,对象是具体的存在,而类仅仅只是一个概念,并不真实存在

(2)程序中
  • 在程序中:务必保证先定义类,后产生对象

  • 这与函数的使用是类似的,先定义函数,后调用函数,类也是一样的,在程序中需要先定义类,后调用类

  • 不一样的是,调用函数会执行函数体代码返回的是函数体执行的结果,而调用类会产生对象,返回的是对象

【四】面对对象编程

  • 关键字 class 声明一个类

  • 在类程序中,特征用变量名标识,功能用函数标识

  • 因而在类中 函数名和变量名

【1】定义类

(1)类名 建议是驼峰体,例如:Student
  • 方式一:class Student(object)

  • 方式二:class Student()

  • 方式三:class Student

复制代码
class Student(object):
    # 类名后面的()参数不写的话默认就是object
    # object:父类
    # 直接定义数据属性
    school_name = "清华"
    
    
    # 函数属性
    def read(self):
        age = 18
        # self:表示对象自己本身
        print(f"当前学校是{self.school_name}")
        
​
# 通过实例化得到一个对象
student = Student()
print(student)      # <__main__.Student object at 0x000001399554FFD0>
# 想用类里面的属性和方法
print(student.school_name)
print(student.read())

【2】类的调用

(1)实例化类,得到对象
复制代码
student_one = Student()
student_two = Student()
​
# 每一次得到的对象都是新的
print(id(student_one))
# 2274496937888
print(id(student_two))
# 2274496937696
(2)如何修改对象的属性
复制代码
# 【1】通过类的名称空间修改属性
# 类的名称空间不允许修改属性
space_class = Student.__dict__
print(space_class, type(space_class))  # <class 'mappingproxy'>
​
# 这两种方式都可以获取
print(space_class['school_name'])
print(space_class.get('school_name'))
​
​
# 【2】修改对象的属性
class Student(object):
    # 数据属性
    school_name = '清华'
​
    # 函数属性
    def read(self):
        age = 18
        # self:表示对象自己本身
        print(f"当前学校是{self.school_name}")
​
​
student = Student()
student_one= Student()
# 添加一个student字典,赋给obj_space
obj_space = student.__dict__
# 添加一个键为name,值为knight的键值对
obj_space['name'] = 'knight'
print(obj_space,type(obj_space))    # {'name': 'knight'} <class 'dict'>
print(obj_space['name'])        # knight
​
# 输出里面定义过的学校名
print(student.school_name)      # 清华
# 输出添加后的name值
print(student.name)             # knight
# student_one是复制的student
print(student_one.school_name)  # 清华
​
​
# 【3】批量修改属性
class Student(object):
    # 数据属性
    school_name = '清华'
​
    # 函数属性
    def read(self):
        age = 18
        # self:表示对象自己本身
        print(f"当前学校是{self.school_name}")
​
​
student_one = Student()
student_two = Student()
# 方式一:通过名称空间字典替换
student_one.__dict__['name'] = 'knight'
# 方式二:通过  对象.属性名=属性值替换
# (1)逐个添加
student_one.name = 'knight'
student_one.age = 18
student_one.gender = 'male'
student_two.name = 'opp'
student_two.age = 19
student_two.gender = 'female'
print(student_one.name)     # knight
print(student_one.age)      # 18
print(student_one.gender)   # male
# (2)批量向对象中添加各自独有的属性值和属性名
def init_obj(obj,name,age,gender):
    obj.name = name
    obj.age = age
    obj.gender = gender
student_one = Student()
student_two = Student()
init_obj(obj=student_one,name='knight',age=18,gender='male')
print(student_one.name)
(3)在类内部初始化自己的参数
复制代码
class Student(object):
    # 数据属性
    school_name = '清华'
​
    def init_obj(self, name, age, gender):  # 这个self就是类的对象本身
        self.name = name
        self.age = age
        self.gender = gender
​
    # 函数属性
    def read(self):
        # self:表示对象自己本身
        print(f"当前学校是{self.school_name}")
        print(f"当前姓名是{self.name}")
        print(f"当前年龄是{self.age}")
        print(f"当前性别是{self.gender}")
student = Student()
# 给值,初始化
student.init_obj(name='knight',age=20,gender='male')
student.read()
(4)魔法方法值初始化方法 __init__
复制代码
class Student(object):
    # 数据属性
    school_name = '清华'
​
    def __init__(self, name, age, gend  er):  # 这个self就是类的对象本身
        self.name = name
        self.age = age
        self.gender = gender
​
    # 函数属性
    def read(self):
        # self:表示对象自己本身
        print(f"当前学校是{self.school_name}")
        print(f"当前姓名是{self.name}")
        print(f"当前年龄是{self.age}")
        print(f"当前性别是{self.gender}")
​
​
# 给值,初始化
student = Student(name='knight',age=20,gender='male')
student.read()
# 需要再添加学生的信息
student_one = Student(name='hyt',age=22,gender='female')
student_one.read()
# 查看类的名称空间
print(student.__dict__) # {'name': 'knight', 'age': 20, 'gender': 'male'}
(5)属性查找顺序
复制代码
class Student(object):
    # 数据属性
    school_name = '清华'
​
    def __init__(self, name, age, gender):  # 这个self就是类的对象本身
        self.name = name
        self.age = age
        self.gender = gender
​
    # 函数属性
    def read(self):
        # self:表示对象自己本身
        print(f"当前学校是{self.school_name}")
        print(f"当前姓名是{self.name}")
        print(f"当前年龄是{self.age}")
        print(f"当前性别是{self.gender}")
​
​
# 给值,初始化
student = Student(name='knight',age=20,gender='male')
print(student.name)
# 可以通过.覆盖原来的值
student.name = 'hyt'    # student.__dict__['name'] = 'hyt'
print(student.name)
​
# 属性查找顺序
print(student.name)
print(student.school_name)
# 查找顺序
# 首先在自己的对象中查找
# 自己找不到就去父类里面找
# 父类没找到就去基类中找
# 如果基类里面也没有,就去object中找
# 否则报错
(6)列表特性回顾
复制代码
num_one_list = [1, 2, 3, 4]
num_two_list = [5, 6, 7, 8]
num_one_list.append(9)
# 每一个列表都是一个单独的对象
print(num_one_list)
print(num_two_list)
​
​
class Student:
    def __init__(self, name):
        self.name = name
​
​
s1 = Student(name='knight')
print(id(s1))
s1.name = 'hyt'
print(id(s1))

【3】类的属性扩展

复制代码
class Duck(Animal,object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
​
    def speak(self):
        print(f"这是一一只鸭子叫{self.name}已经{self.age}岁了")
​
​
duck = Duck(name='tang', age=1)
# 属性介绍
# 【1】获取当前类的名字
print(Duck.__name__)
# 【2】获取类中文档字符串(只能获取三引号中的)
print(Duck.__doc__)
# 【3】获取类的父类
print(Duck.__base__)    # <class '__main__.Animal'>
# 【4】获取类的所有父类
print(Duck.__bases__)   # (<class '__main__.Animal'>, <class 'object'>)
# 【5】获取当前类的名称空间(字典)
print(Duck.__dict__)
# 【6】获取类定义所在的模块名
print(Duck.__module__)  # __main__
# 【7】实例化得到对象
相关推荐
义小深几秒前
TensorFlow|咖啡豆识别
人工智能·python·tensorflow
疯一样的码农5 分钟前
Python 正则表达式(RegEx)
开发语言·python·正则表达式
进击的六角龙1 小时前
Python中处理Excel的基本概念(如工作簿、工作表等)
开发语言·python·excel
一只爱好编程的程序猿1 小时前
Java后台生成指定路径下创建指定名称的文件
java·python·数据下载
Aniay_ivy2 小时前
深入探索 Java 8 Stream 流:高效操作与应用场景
java·开发语言·python
gonghw4032 小时前
DearPyGui学习
python·gui
向阳12182 小时前
Bert快速入门
人工智能·python·自然语言处理·bert
engchina2 小时前
Neo4j 和 Python 初学者指南:如何使用可选关系匹配优化 Cypher 查询
数据库·python·neo4j
兆。2 小时前
掌握 PyQt5:从零开始的桌面应用开发
开发语言·爬虫·python·qt
南宫理的日知录2 小时前
99、Python并发编程:多线程的问题、临界资源以及同步机制
开发语言·python·学习·编程学习