面向对象

面向对象

  • 面向对象编程思想前戏
  • 面向过程编程与面向对象编程
  • 类与对象的概念
  • 代码编写类
  • 代码产生对象
  • 类与对象的具体操作

面向对象编程思想前戏

# 英雄联盟打野小游戏
# 描述英雄与野怪
# 方式1:定义英雄字典与野怪字典进行描述
creeps1 = {
    'name': '蜥蜴',
    'type': '小野怪',
    'attack_val': 30,
    'life_val': 200
}
creeps2 = {
    'name': '蛤蟆',
    'type': '大野怪',
    'attack_val': 180,
    'life_val': 500
}
hero1 = {
    'name': '疾风剑豪',
    'type': '刺客',
    'attack_val': 100,
    'life_val': 1000
}


# 方式2:封装成函数 减少代码冗余
# 定义专门用来描述英雄和野怪的函数(最好单独编写)
def get_hero(name, gender, t_type, attack_val, life_val):
    data_dict = {
        'name': name,
        'gender': gender,
        't_type': t_type,
        'attack_val': attack_val,
        'life_val': life_val
    }
    return data_dict


def get_creeps(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


h1 = get_hero('疾风剑豪', 'male', '刺客', 800, 1000)
h2 = get_hero('冰晶凤凰', 'female', '战士', 200, 800)
c1 = get_creeps('蛤蟆', '大野怪', 300, 500)
c2 = get_creeps('蜥蜴', '小野怪', 50, 200)


def creeps_attack(creeps_obj, hero_obj):
    """
    :param creeps_obj: 接收一只野怪
    :param hero_obj: 接收一个英雄
    """
    # 使用最简答的掉血逻辑  血量减去对方攻击力
    print('当前英雄的血量是:%s' % hero_obj.get('life_val'))
    hero_obj['life_val'] -= creeps_obj.get('attack_val')
    print("""野怪:%s 攻击英雄:%s 一下 英雄掉血:%s 剩余血量:%s""" % (
    creeps_obj.get('name'), hero_obj.get('name'), creeps_obj.get('attack_val'), hero_obj['life_val']))


def hero_attack(hero_obj, creeps_obj):
    """
    :param hero_obj: 接收一个英雄
    :param creeps_obj: 接收一只野怪
    """
    print('当前野怪的血量是:%s' % creeps_obj.get('life_val'))
    creeps_obj['life_val'] -= hero_obj.get('attack_val')
    print("""英雄:%s 攻击野怪了:%s 一下 野怪掉血:%s 剩余血量:%s""" % (
    hero_obj.get('name'), creeps_obj.get('name'), hero_obj.get('attack_val'), creeps_obj['life_val']))

creeps_attack(c2, h1)
print(h1)

hero_attack(h2, c1)
print(c1)
"""但是这样写,野怪也会调用英雄的函数,如何实现只让各自的对象调用相对应的函数?
	答案是将数据和功能进行绑定
	"""

def get_hero(name, gender, t_type, attack_val, life_val):
    def hero_attack(hero_obj, creeps_obj):
        """
        :param hero_obj: 接收一个英雄
        :param creeps_obj: 接收一只野怪
        """
        print('当前野怪的血量是:%s' % creeps_obj.get('life_val'))
        creeps_obj['life_val'] -= hero_obj.get('attack_val')
        print("""英雄:%s 攻击野怪了:%s 一下 野怪掉血:%s 剩余血量:%s""" % (
        hero_obj.get('name'), creeps_obj.get('name'), hero_obj.get('attack_val'), creeps_obj['life_val']))
        return hero_attack
    data_dict = {
        'name': name,
        'gender': gender,
        't_type': t_type,
        'attack_val': attack_val,
        'life_val': life_val,
        'hero_attack': hero_attack
    }
    return data_dict
def get_creeps(name, t_type, attack_val, life_val):
    def creeps_attack(creeps_obj, hero_obj):
        """
        :param creeps_obj: 接收一只野怪
        :param hero_obj: 接收一个英雄
        """
        # 使用最简答的掉血逻辑  血量减去对方攻击力
        print('当前英雄的血量是:%s' % hero_obj.get('life_val'))
        hero_obj['life_val'] -= creeps_obj.get('attack_val')
        print("""野怪:%s 攻击英雄:%s 一下 英雄掉血:%s 剩余血量:%s""" % (
        creeps_obj.get('name'), hero_obj.get('name'), creeps_obj.get('attack_val'), hero_obj['life_val']))
        return creeps_attack
    data_dict = {
        'name': name,
        't_type': t_type,
        'attack_val': attack_val,
        'life_val': life_val,
        'creeps_attack': creeps_attack
    }
    return data_dict
h1 = get_hero('疾风剑豪', 'male', '刺客', 800, 1000)
h2 = get_hero('冰晶凤凰', 'female', '战士', 200, 800)
c1 = get_creeps('蛤蟆', '大野怪', 300, 500)
c2 = get_creeps('蜥蜴', '小野怪', 50, 200)
h2['hero_attack'](h2,c1)
"""
上述操作就是绑定数据与功能的体现
"""
image-20220406180116121

编程思想

1.面向过程编程
	将程序的执行流程化 即分步操作 分步的过程中解决问题
  	eg:注册、登录、结算购物车...
      """注册:第一步获取用户名 第二步比对用户名数据 ..."""
      """结算:第一步获取购物车数据 第二步计算钱数   ..."""
	过程可以理解成是流水线 面向过程编程可以理解成是在创建一条流水线
2.面向对象编程
	核心就是'对象'二字 
		对象其实就是一个"容器" 将数据与功能整合到一起
  只要是符合上述描述的事物都可以称之为是对象!!!
  	eg:
      打野游戏最后的函数内部含有数据和功能 可以称之为面向对象编程
      模块文件内部含有数据和功能 也可以称之为面向对象编程
  """仔细的想想会发现 python中一切皆对象!!!"""
  python针对面向对象编程提供了专门的语法 识别度更高 编写更精简
		eg:人、动物、游戏角色
"""
面向过程与面向对象两者没有优劣之分 具体要结合实际情况
甚至很多时候两者是混合在一起的!!! 思想占据的比例不同而已
"""

类与对象的功能

对象: 数据与功能的结合体
类:	 类别 、种类、相当于诸多对象公有的特征(数据、功能)
eg:
    人					对象
	一群人			 		人类

	狗				  对象
	一群狗      			犬类
"""其实类也属于对象>>>>>>>>:结论>>>>>>>: 一切皆对象"""
image-20220406183435799

类与对象的创建

"""
在实际代码的编写中,是先有类,再有对象
"""
# 先定义类 后产生对象
# 学生类
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)  # 北京大学

对象的实例化

# 学生类
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()  # 目前对象没有自己独有的属性
# obj2 = Student()  # 目前对象没有自己独有的属性
# print(obj1.__dict__)  # 大白话就是给字典添加键值对
# print(obj2.__dict__)  # 大白话就是给字典添加键值对
'''方案1:逐步给对象添加独有的数据'''
# obj1.__dict__['name'] = 'jason'  # obj1.name = 'jason'
# obj1.__dict__['age'] = 18  # obj1.age = 18
# obj1.__dict__['gender'] = 'male'  # obj1.gender = 'male'

# obj2.__dict__['name'] = 'kevin'  # obj2.name = 'kevin'
# obj2.__dict__['age'] = 2  # obj2.age = 28
# obj2.__dict__['gender'] = 'female'  # obj2.gender = 'female'
# print(obj1.__dict__,obj2.__dict__)
# print(obj1.name)  # jason
# print(obj2.name)  # kevin
'''方案2:将冗余的添加步骤封装成函数'''
# def init(obj,name,age,gender):
#     obj.name = name  # obj.__dict__['name'] = name
#     obj.age = age  # obj.__dict__['age'] = age
#     obj.gender = gender  # obj.__dict__['gender'] = gender
# init(obj1,'jason',18,'male')
# init(obj2,'kevin',28,'female')
# print(obj1.name)
# print(obj2.name)
'''方案3:简单的封装成函数没有提现出面向对象整合的精髓>>>:将函数写到类中去'''
# obj1 = Student()
# obj2 = Student()
# Student.set_info(obj1,'jason',18,'male')
# Student.set_info(obj2,'kevin',28,'female')
# print(obj1.name)  # jason
# print(obj2.name)  # kevin
'''方案4:类中针对给对象创建独有数据的函数名 专门定义了一个固定的方法'''
# obj1 = Student('jason', 18, 'male')
# obj2 = Student('kevin', 28, 'female')
# print(obj1.__dict__)
# print(obj2.__dict__)
"""
类中的__init__方法会在类产生对象的时候自动执行
类产生对象的具体步骤
    1.先创建一个没有独有数据的空对象  {}
    2.将空对象和类括号内传入的数据一并交给__init__执行
        __init__的第一个参数就是对象本身
            __init__(obj,name,age,gender)
    3.将创建好的对象自动返回
给你提供这种方式能够减少代码的编写

ps:针对括号内第一个形参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'''
image-20220406211613079
posted @ 2022-04-06 21:18  DDYT  阅读(76)  评论(0)    收藏  举报