【python基础】第33回 面向对象

1. 面向对象前戏

1.1 人狗大战,创造出人和狗

1.1.1 推导步骤1

# 1. 创造出人和狗
'''推导步骤 1 直接手写字典模拟一个个人和狗'''
person1 = {
    'name': 'zhang',
    'p_type': '猛男',
    'attack_val': 10,
    'life_val': 100
}
dog1 = {
    'name': '小黑',
    'p_type': '金毛',
    'attack_val': 10,
    'lisfe_val': 50
}

1.1.2 推导步骤2

'''推到步骤2 由于定义人和狗的字典基本不变,但是在很多地方又需要反复使用,所以封装成函数'''
def get_person(name, gender, age, d_type, attack_val, life_val):
    """
    专用用于产生用户字典(创造人)
    :param name: 姓名
    :param gender: 性别
    :param age: 年龄
    :param d_type: 类型
    :param attack_val:攻击力
    :param life_val: 生命值
    :return: 人的字典(人)
    """
    person_obj = {
        'name': name,
        'gender': gender,
        'age': age,
        'd_type': d_type,
        'attack_val': attack_val,
        'life_val': life_val
    }
    return person_obj

p1 = get_person('jason', 'male', 18, '猛男', 10, 100)
p2 = get_person('li', 'male', 18, '淑女', 10, 50)

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

d1 = get_dog('小黄狗','中华田园犬',8, 50)
d2 = get_dog('小奶狗','哈士奇',5, 20)

1.1.3 推导步骤3

'''推导步骤3:让人和狗具备攻击的能力,本质其实就是定义两个函数供人和狗调用'''

def person_attack(person_obj, dog_obj):
    """
    专用提供给人调用 攻击狗
    :param person_obj: 传人数据(字典)
    :param dog_obj: 传狗数据(字典)
    """
    print('即将被攻击的狗:%s 当前血量:%s' % (dog_obj.get('name'),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.get('life_val')))

def dog_attack(dog_obj, person_obj):
    """
    专用提供给狗调用 攻击人
    :param dog_obj: 传狗数据(字典)
    :param person_obj: 传人数据(字典)
    """
    print('即将被攻击的人:%s 当前血量:%s' % (person_obj.get('name'), 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.get('life_val')))

# 调用产生人和狗的函数
p1 = get_person('jason', 'male', 18, '猛男', 10, 100)
p2 = get_person('li', 'male', 18, '淑女', 10, 50)
d1 = get_dog('小黄狗','中华田园犬',8, 50)
d2 = get_dog('小奶狗','哈士奇',5, 20)

# 调用攻击彼此的函数
person_attack(p1,d1)
dog_attack(d2,p2)

1.2 代码优化

1.2.1 推导步骤4

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

"""推导步骤4: 人和狗攻击乱套"""
person_attack(d2, p1)
dog_attack(p2, d1)

1.2.2 推导步骤5

"""推导步骤5: 人跟人攻击狗的函数绑定 狗跟狗攻击人的函数绑定
我们定义的函数默认情况下都是可以被任意调用的 但是现在我们想实现定义的函数只有特定的东西才可以调用
"""

def get_person(name, gender, age, p_type, attack_val, life_val):
    """
    专用用于产生用户字典(创造人)
    :param name: 姓名
    :param gender: 性别
    :param age: 年龄
    :param d_type: 类型
    :param attack_val:攻击力
    :param life_val: 生命值
    :return: 人的字典(人)
    """
    def person_attack(person_obj, dog_obj):
        """
        专用提供给人调用 攻击狗
        :param person_obj: 传人数据(字典)
        :param dog_obj: 传狗数据(字典)
        """
        print('即将被攻击的狗:%s 当前血量:%s' % (dog_obj.get('name'), 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.get('life_val')))
    person_obj = {
        'name': name,
        'gender': gender,
        'age': age,
        'p_type': p_type,
        'attack_val': attack_val,
        'life_val': life_val,
        'person_attack':person_attack
    }
    return person_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, person_obj):
        """
        专用提供给狗调用 攻击人
        :param dog_obj: 传狗数据(字典)
        :param person_obj: 传人数据(字典)
        """
        print('即将被攻击的人:%s 当前血量:%s' % (person_obj.get('name'), 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.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
d1 = get_dog('小黄狗', '恶霸犬', 5,50 )
p1 = get_person('jason', 'male', 18, '猛男', 8, 80)
p1.get('person_attack')(p1, d1)

1.3 总结

  1. 将人的数据跟人的功能绑定到一起,只有人可以调用人的功能
  2. 将狗的数据跟狗的功能绑定到一起,只有狗可以调用狗的功能
  3. 我们将数据与功能绑定到一起的操作起名为:'面向对象编程'
  4. 本质:将特定的数据与特定的功能绑定到一起,将来只能彼此相互使用

2. 编程思想(面向过程,面向对象)

2.1 面向过程编程

  1. 过程其实就是流程,面向过程编程其实就是在执行一系列的流程
    eg: 注册功能 登录功能 充值功能等
  2. 即就是按照指定的步骤依次执行,最终就可以得到想要的结果

2.2 面向对象编程

  1. 核心就是'对象'二字,对象其实就是一个容器,里面将数据和功能绑定在一起
  2. eg: 游戏人物... 只负责创造出该人物以及该人物具备的功能,至于后续战绩如何无人知晓

2.3 总结

  1. 面向过程编程相当于让你给出一个问题的具体解决方案
  2. 面向对象编程相当于让你创造出一些事物之后不用你管
  3. 两种编程思想没有优劣之分 仅仅是使用场景不同,甚至很多时候是两者混合使用

3. 类与对象的概念

3.1 对象:数据与功能的结合体

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

3.3 类比

类比学习法
	一个人   对象
	多个人	人类
	
	一条狗	对象
	多条狗	犬类
  1. 类主要用于记录多个对象相同的数据和功能
  2. 对象则用于记录多个对象不同的数据和功能
  3. 在面向对象编辑中,类仅仅是用于节省代码,对象才是核心

4. 类与对象的创建

4.1 理解

  1. 在现实生活中理论是应该先有一个个的个体(对象)再有一个个的群体(类)
  2. 在编程世界中必须先有类才能产生对象
  3. 面向对象编程本质就是将数据和功能绑定到一起,但是为了突出面向对象编程的形式
  4. python特地开发了一套语法专门用于面向对象编辑的操作

4.2 创捷类的完整语法

calss 类的名称:
      # 对象公共的数据,方法信息
  1. calss 是类的名字
  2. 后面是类的名称,类名的命名跟变量名一致,并且推荐首字母大写(为了更好的区分)
  3. 类体代码:公共的数据\公共的方法
  4. 类体代码在类定义阶段就会执行
def dunc():
    print('不会打印')
class A:
    print('会打印')

4.3 查看名称空间的方法

4.3.1 查看

class People:
    # 学生对象公共的数据
    school = '清华大学'
    # 学生对象公共的方法
    def choice_course(self):
        print('正在选课')
# 查看名称空间的方法
print(People.__dict__) # 使用该方法查看名称空间 可以看成是一个字典

4.3.2 字典取值

print(People.__dict__['school'])  # 使用字典的取值方式获取名字
print(People.__dict__.get('choice_course'))  # 使用字典的取值方式获取名字

4.3.3 句点符取值

<function People.choice_course at 0x0000023B62878670>

5. 对象的实例化方法(独有数据)

5.1 我们习惯将类或者对象句点符后面的东西称为属性名或者方法名

5.2 实例化方法

class Student:
    # 学生对象公共的数据
    school = '清华大学'
    # 学生对象公共的方法
    def choice_course(self):
        print('正在选课')
'''类实例化产生对象>>>: 类名加括号'''
# 类名加括号,每次都会产生全新的对象
stu1 = Student()
stu2 = Student()
print(stu1)  # <__main__.Student object at 0x000001895D834A60>
print(stu2)  # <__main__.Student object at 0x000001895D86F130>
print(stu1.__dict__, stu2.__dict__)  # {} {}
print(stu1.school)  # 清华大学
print(stu2.school)  # 清华大学
print(stu1.choice_course)  # <bound method Student.choice_course of <__main__.Student object at 0x0000020F3A5E4A60>>
print(stu2.choice_course)  # <bound method Student.choice_course of <__main__.Student object at 0x0000020F3A61F130>>

5.3 修改值

# 类名加括号,每次都会产生全新的对象
stu1 = Student()
stu2 = Student()
print(stu1.school)  # 清华大学
print(stu2.school)  # 清华大学
# print(stu1)  # <__main__.Student object at 0x000001895D834A60>
# print(stu2)  # <__main__.Student object at 0x000001895D86F130>
# print(stu1.__dict__, stu2.__dict__)  # {} {}
Student.__dict__['school'] = '北京大学'
print(stu1.school)  #
print(stu2.school)  #

# 类名加括号,每次都会产生全新的对象
stu1 = Student()
stu2 = Student()
print(stu1.school)  # 清华大学
print(stu2.school)  # 清华大学
# print(stu1)  # <__main__.Student object at 0x000001895D834A60>
# print(stu2)  # <__main__.Student object at 0x000001895D86F130>
# print(stu1.__dict__, stu2.__dict__)  # {} {}
Student.school = '北京大学'
print(stu1.school)  # 北京大学
print(stu2.school)  # 北京大学

6. 对象的绑定方法(独有功能)

6.1 推导思路1:直接利用__dict__方法朝字典添加键值对

class Student:
    # 学生对象公共的数据
    school = '清华大学'
    # 学生对象公共的方法
    def choice_course(self):
        print('正在选课')
# 对象独有的数据
obj1 = Student()
print(obj1.__dict__)  # {}
print(obj1.school)  # 清华大学
obj1.__dict__['name'] = 'jason'  # 等价于 obj1.name = 'jason'
print(obj1.__dict__)  # {'name': 'jason'}
print(obj1.name)  # jason
obj1.__dict__['age'] = 18  # 等价于 obj1.age = 18
obj1.__dict__['gender'] = 'male'  # 等价于 obj1.gender = 18
print(obj1.age)  # 18
print(obj1.gender)  # male
print(obj1.__dict__)  # {'name': 'jason', 'age': 18, 'gender': 'male'}

6.2 推导思路2:将添加独有数据的代码封装成函数

'''推导思路2: 将添加独有数据的代码封装成函数'''
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')
init(stu2, 'kevin',28,'female')
print(stu1.__dict__)  # {'name': 'jason', 'age': 18, 'gender': 'male'}
print(stu2.__dict__)  # {'name': 'kevin', 'age': 28, 'gender': 'female'}

6.3 推导思路3: init函数是专用给学生对象创建独有的数据 其他对象不能调用

class Student:
    """
    1.先产生一个空对象
    2.自动调用类里面的__init__方法 将产生的空对象当成第一个参数传入
    3.将产生的对象返回出去
    4.自动把self当作第一对象传过来
    """
    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.__dict__)  # {'name': 'jason', 'age': 18, 'gender': 'male'}
stu2 = Student('kevin', 28, 'female')
print(stu2.__dict__)  # {'name': 'kevin', 'age': 28, 'gender': 'female'}
posted @ 2022-07-26 19:47  |相得益张|  阅读(34)  评论(0编辑  收藏  举报