一、面向对象推导——人狗大战

1.案例:人狗大战

1.1.推导步骤1:字典模拟人和狗

human1 = {  # 使用字典模拟人
    'name': 'jason',
    'p_type': '猛男',
    'attack_val': 800,
    'life_val': 2000

dog1 = {  # 使用字典模拟狗
    'name': '小白',
    'd_type': '阿拉斯加',
    'attack_val': 1000,
    'life_val': 2000
}

1.2.推导步骤2:封装函数

由于定义人和狗的字典基本不变,但是在很多地方又需要反复使用,所以封装成函数

def get_human(name, gender, age, h_type, attack_val, life_val):
    """
    专用用于产生用户字典(创造人)
    :param name: 姓名
    :param gender: 性别
    :param age: 年龄
    :param h_type: 类型
    :param attack_val:攻击力
    :param life_val: 生命值
    :return: 人的字典(人)
    """
    human_obj = {
        'name': name,
        'gender': gender,
        'age': age,
        'p_type': h_type,
        'attack_val': attack_val,
        'life_val': life_val
    }
    return human_obj


human = get_human('jason', 'male', 28, '猛男', 800, 2000)


def get_dog(name, d_type, attack_val, life_val):
    """
    专门用于产生狗字典(狗)
    :param name: 狗的名字
    :param d_type: 狗的类型
    :param attack_val: 狗的攻击力
    :param life_val: 狗的生命值
    :return: 狗的字典(狗)
    """
    dog_obj = {
        'name': name,
        'd_type': d_type,
        'attack_val': attack_val,
        'life_val': life_val
    }
    return dog_obj


dog = get_dog('小白狗', '阿拉斯加', 1000, 2000)

1.3.推导步骤3:定义两个函数供人和狗调用

让人和狗具备攻击的能力,本质其实就是定义两个函数供人和狗调用

def human_attack(human_obj, dog_obj):
    """
    专用提供给人调用 攻击狗
    :param human_obj: 传人数据(字典)
    :param dog_obj: 传狗数据(字典)
    """
    print('即将被攻击的狗:%s 当前血量:%s' % (dog_obj.get('name'), dog_obj.get('life_val')))  # 先展示当前狗的状态
    dog_obj['life_val'] -= human_obj.get('attack_val')  # 人锤狗 直接用狗的生命值减去人的攻击力
    print('人:%s 锤了 狗:%s 狗掉血:%s 剩余血量:%s' % (
        human_obj.get('name'), dog_obj.get('name'), human_obj.get('attack_val'), dog_obj.get('life_val')))


def dog_attack(dog_obj, human_obj):
    """
    专用提供给狗调用 攻击人
    :param dog_obj: 传狗数据(字典)
    :param human_obj: 传人数据(字典)
    """
    print('即将被攻击的人:%s 当前血量:%s' % (human_obj.get('name'), human_obj.get('life_val')))  # 先展示当前人的状态
    human_obj['life_val'] -= dog_obj.get('attack_val')  # 狗咬人 直接用人的生命值减去狗的攻击力
    print('狗:%s 咬了 人:%s 人掉血:%s 剩余血量:%s' % (
        dog_obj.get('name'), human_obj.get('name'), dog_obj.get('attack_val'), human_obj.get('life_val')))


# 调用产生人和狗的函数
human1 = get_human('jason', 'male', 28, '猛男', 800, 2000)
human2 = get_human('tom', 'male', 18, '弱男', 100, 1200)
dog1 = get_dog('小白狗', '阿拉斯加', 1000, 2000)
dog2 = get_dog('小黑狗', '藏獒', 2000, 8000)
# 调用攻击彼此的函数
human_attack(human1, dog1)
# 即将被攻击的狗:小白狗 当前血量:2000
# 人:jason 锤了 狗:小白狗 狗掉血:800 剩余血量:1200

dog_attack(dog2, human2)
# 即将被攻击的人:tom 当前血量:1200
# 狗:小黑狗 咬了 人:tom 人掉血:2000 剩余血量:-800

1.4.推导步骤4:人和狗攻击的函数,可以被任意调用

人和狗攻击乱套(人和狗攻击的函数,可以被任意调用)
人可以调用狗攻击的功能,狗可以调用人攻击的功能

human_attack(dog2, human1)
# 即将被攻击的狗:jason 当前血量:2000
# 人:小黑狗 锤了 狗:jason 狗掉血:2000 剩余血量:0

dog_attack(human2, dog1)
# 即将被攻击的人:小白狗 当前血量:2000
# 狗:tom 咬了 人:小白狗 人掉血:100 剩余血量:1900

1.5.推导步骤5:人跟人攻击狗的函数绑定,狗跟狗攻击人的函数绑定

人跟人攻击狗的函数绑定,狗跟狗攻击人的函数绑定

我们定义的函数默认情况下都是可以被任意调用的 但是现在我们想实现定义的函数只有特定的东西才可以调用

def get_human(name, gender, age, h_type, attack_val, life_val):
    """
    专用用于产生用户字典(创造人)
    :param name: 姓名
    :param gender: 性别
    :param age: 年龄
    :param h_type: 类型
    :param attack_val:攻击力
    :param life_val: 生命值
    :return: 人的字典(人)
    """
    def human_attack(human_obj, dog_obj):
        """
        专用提供给人调用 攻击狗
        :param human_obj: 传人数据(字典)
        :param dog_obj: 传狗数据(字典)
        """
        print('即将被攻击的狗:%s 当前血量:%s' % (dog_obj.get('name'), dog_obj.get('life_val')))  # 先展示当前狗的状态
        dog_obj['life_val'] -= human_obj.get('attack_val')  # 人锤狗 直接用狗的生命值减去人的攻击力
        print('人:%s 锤了 狗:%s 狗掉血:%s 剩余血量:%s' % (
            human_obj.get('name'), dog_obj.get('name'), human_obj.get('attack_val'), dog_obj.get('life_val')))

    human_obj = {
        'name': name,
        'gender': gender,
        'age': age,
        'h_type': h_type,
        'attack_val': attack_val,
        'life_val': life_val,
        'human_attack': human_attack
    }
    return human_obj


def get_dog(name, d_type, attack_val, life_val):
    """
    专门用于产生狗字典(狗)
    :param name: 狗的名字
    :param d_type: 狗的类型
    :param attack_val: 狗的攻击力
    :param life_val: 狗的生命值
    :return: 狗的字典(狗)
    """
    def dog_attack(dog_obj, human_obj):
        """
        专用提供给狗调用 攻击人
        :param dog_obj: 传狗数据(字典)
        :param human_obj: 传人数据(字典)
        """
        print('即将被攻击的人:%s 当前血量:%s' % (human_obj.get('name'), human_obj.get('life_val')))  # 先展示当前人的状态
        human_obj['life_val'] -= dog_obj.get('attack_val')  # 狗咬人 直接用人的生命值减去狗的攻击力
        print('狗:%s 咬了 人:%s 人掉血:%s 剩余血量:%s' % (
            dog_obj.get('name'), human_obj.get('name'), dog_obj.get('attack_val'), human_obj.get('life_val')))

    dog_obj = {
        'name': name,
        'd_type': d_type,
        'attack_val': attack_val,
        'life_val': life_val,
        'dog_attack': dog_attack
    }
    return dog_obj


dog1 = get_dog('小白狗', '阿拉斯加', 1000, 2000)
human1 = get_human('jason', 'male', 28, '猛男', 800, 2000)
human1.get('human_attack')(human1, dog1)
# 即将被攻击的狗:小白狗 当前血量:2000
# 人:jason 锤了 狗:小白狗 狗掉血:800 剩余血量:1200

2.推导总结

  • 将人的数据跟人的功能绑定到一起,只有人可以调用人的功能
  • 将狗的数据跟狗的功能绑定到一起,只有狗可以调用狗的功能

我们将数据与功能绑定到一起的操作起名为:面向对象编程

本质:将特定的数据与特定的功能绑定到一起,将来只能彼此相互使用

二、编程思想

编程程思想大致可以分为面向过程编程面向对象编程两种,这两种编程思想没有优劣之分,仅仅是使用场景不同,甚至很多时候是两者混合使用

1.面向过程编程

概念:面向过程编程其实就是在执行一系列的流程,按照指定的步骤依次执行,最终得到想要的结果,相当于给出一个问题的具体解决方案

2.面向对象编程

核心:对象

概念:对象其实就是一个容器,将数据和功能绑定到了一起,相当于让创造出一些事物之后不用管

本质:将特定的数据与特定的功能绑定到一起,将来只能彼此相互使用

注意:面向过程编程和面向对象编程没有优劣之分,只是使用场景不同,很多时候还是两者混用

三、对象与类的简介

1.对象

概念:数据与功能的结合体

作用:用于记录多个对象不同的数据和功能

2.类

概念:多个对象相同的数据和功能的结合体

作用:用于记录多个对象相同的数据和功能

注意:类或者对象句点符后面的东西称为属性名或者方法名

3.类比学习法

例子 对象/类
一个人 对象
多个人 人类
一条狗 对象
多条狗 犬类

四、对象与类的创建

在现实生活中理论是应该先有一个个的个体(对象)再有一个个的群体(类),在编程世界中必须要先有类才能产生对象

1.语法

class People:
    # 公共的数据
    # 公共的方法
  1. class:定义类的关键字
  2. People:类名
    • 类名的命名跟变量名一致,首字母大写(为了更好的区分)
  3. 类体代码(公共的数据\方法)
    • 类体代码在类定义阶段就会执行

2.Python内置类属性

类属性 描述
__ dict__ 类的属性(包含一个字典,由类的数据属性组成)
__ doc__ 类的文档字符串
__ name__ 类名
__ module__ 类定义所在的模块(类的全名是'main.className',如果类位于一个导入模块mymod中,那么className.module 等于 mymod)
__ bases__ 类的所有父类构成元素(包含了一个由所有父类组成的元组)

3.查看名称空间的方法

# 学生类
class Student:
    # 学生对象公共的数据
    school = '清华大学'
 
    # 学生对象公共的方法
    def choice_course(self):
        print('正在选课')

print(Student.__dict__)  # 使用该方法查看名称空间 可以看成是一个字典
print(Student.__dict__['school'])  # 使用字典的取值方式获取名字
print(Student.__dict__.get('choice_course'))  # 使用字典的取值方式获取名字

在面向对象编程中,获取名称空间中的名字,可以采用句点符和字典的取值两种方式方式

print(Student.school)
print(Student.choice_course)

4.类实例化产生对象

类名加括号

class Student:
    # 学生对象公共的数据
    school = '清华大学'
 
    # 学生对象公共的方法
    def choice_course(self):
        print('正在选课')

stu1 = Student()
stu2 = Student()
print(stu1.school)  # 清华大学
print(stu2.school)  # 清华大学
print(stu1)  # <__main__.Student object at 0x000001D923B04A60>
print(stu2)  # <__main__.Student object at 0x0000025E8A48F130>
print(stu1.__dict__, stu2.__dict__)  # {} {}
print(stu1.choice_course)  # <bound method Student.choice_course of <__main__.Student object at 0x000001C85CB9C208>>
print(stu2.choice_course)  # <bound method Student.choice_course of <__main__.Student object at 0x000001C85CB9C208>>

5.修改属性值

class Student:
    # 学生对象公共的数据
    school = '清华大学'

Student.school = '北京大学'  # 修改school键对应的值
print(stu1.school)  # 北京大学
print(stu2.school)  # 北京大学

6.对象独有的数据

6.1.推导思路1

直接利用__dict__方法朝字典添加键值对

# 学生类
class Student:
    # 学生对象公共的数据
    school = '清华大学'

    # 学生对象公共的方法
    def choice_course(self):
        print('正在选课')

        
obj1 = Student()
obj1.__dict__['name'] = 'jason'  # 等价于 obj1.name = 'jason'
obj1.__dict__['age'] = 18  # 等价于 obj1.age = 18
obj1.__dict__['gender'] = 'male'  # ...
print(obj1.name)  # jason
print(obj1.age)  # 18
print(obj1.gender)  # male
print(obj1.school)  # 清华大学

6.2.推导思路2

将添加独有数据的代码封装成函数

# 学生类
class Student:
    # 学生对象公共的数据
    school = '清华大学'

    # 学生对象公共的方法
    def choice_course(self):
        print('正在选课')

        
def init(obj, name, age, gender):
    obj.__dict__['name'] = name
    obj.__dict__['age'] = age
    obj.__dict__['gender'] = gender


stu1 = Student()
stu2 = Student()
init(stu1, 'jason', 18, 'male')  # {'name': 'jason', 'age': 18, 'gender': 'male'}
init(stu2, 'kevin', 28, 'female')  # {'name': 'kevin', 'age': 28, 'gender': 'female'}
print(stu1.__dict__)  # <__main__.Student object at 0x0000029E0DAB9358>
print(stu2.__dict__)  # <__main__.Student object at 0x0000029E0DAB92B0>

6.3.推导思路3

init函数是专用给学生对象创建独有的数据

将函数封装到学生类中,这样只有学生类产生的对象才有资格访问

  1. 先产生一个空对象

  2. 自动调用类里面的__init__方法 将产生的空对象当成第一个参数传入

  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 choice_course(self):
        print('正在选课')


stu1 = Student('jason', 18, 'male')
print(stu1)  # <__main__.Student object at 0x000001FEF89FACF8>
stu2 = Student('kevin', 28, 'female')
print(stu2)  # <__main__.Student object at 0x000001FEF89FAAC8>
 posted on 2022-07-26 19:06  念白SAMA  阅读(51)  评论(0编辑  收藏  举报