逆袭之路——python 面向对象编程【day26】

今日内容概要

强调:今日老师讲的内容以理论为主,仅仅是一个思想的解读而已

  • 面向对象编程思想前戏
  • 面向对象编程思想
  • 类与对象的概念
  • 类与对象的创建
  • 对象的实例化
  • 类与对象绑定方法
    请添加图片描述

今日内容详细

一、面向对象编程思想前戏

        首先呢,老师用人狗大战小游戏作为前戏带我们引入面向对象编程思想。

# 人狗大战小游戏
# 1.描述人和狗
'''描述人和狗的方式1:使用字典的形式一个个描述'''
# dog1 = {
#     'name': '小黑',
#     'type': '田园犬',
#     'attack_val': 30,
#     'life_val': 200
# }
# dog2 = {
#     'name': '小白',
#     'type': '恶霸犬',
#     'attack_val': 180,
#     'life_val': 500
# }
# person1 = {
#     'name': '小龙',
#     'type': '猛男',
#     'attack_val': 10,
#     'life_val': 1000
# }
'''方式2:封装成函数 减少代码冗余,不好的一点是人可以调用狗的功能,狗呢,也可以调用人的功能,造成了不一一对应'''

# 定义专门用来描述人和狗的函数(最好单独编写)
# 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)
# p2 = get_person('kevin', 'female', 28, '淑女', 5, 100)
# dog1 = get_dog('小黑', '松狮犬', 300, 500)
# dog2 = get_dog('小白', '泰迪犬', 50, 200)
# 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
p1 = get_person('jason','male',18,'猛男',800, 1000)
p2 = get_person('kevin','female',28,'淑女',10,100)
dog1 = get_dog('小黑', '松狮犬', 300, 500)
dog2 = get_dog('小白', '泰迪犬', 50, 200)
p1['person_attack'](p1,dog1)
dog1['dog_attack'](dog1,p2)
"""
上述操作其实就是将数据与功能进行绑定 
    不再是所有的数据都可以调用任意的功能
"""
# 上述将数据与功能整合到一起的操作其实就是 面向对象编程的思想

二、面向对象编程思想

                                                                面向过程 VS 面向对象

1、面向过程编程

  • 就是将程序的执行流程化 即分步操作 分步的过程中解决问题
  • 面向过程的程序设计的核心是过程(流水线式思维),面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西

优点是:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。

缺点是:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。

2、面向对象编程

  • 面向对象的程序设计的核心是 对象 二字(上帝式思维)
  • 对象其实就是一个 容器 将数据与功能整合到一起,只要是符合上述描述的事物都可以称之为是对象!!!

优点是解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易

缺点是可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果
        于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现,一刀砍死3个人,这个游戏就失去平衡。

通过以上两种解释可以知道:

"""仔细的想想会发现 python中一切皆对象!!!"""
  python针对面向对象编程提供了专门的语法 识别度更高 编写更精简
		eg:人、动物、游戏角色
"""
面向过程与面向对象两者没有优劣之分 具体要结合实际情况
甚至很多时候两者是混合在一起的!!! 思想占据的比例不同而已
"""

三、 类与对象的概念

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

  • : 即类别、种类 相当于诸多对象公有的特征(数据、功能)!!!所以可以知道如果多个对象有相似的数据与功能,那么该多个对象就属于同一种类。有了类的好处是:我们可以把同一类对象相同的数据与功能存放到类里,而无需每个对象都重复存一份,这样每个对象里只需存自己独有的数据即可,极大地节省了空间。所以,如果说对象是用来存放数据与功能的容器,那么类则是用来存放多个对象相同的数据与功能的容器。
    在这里插入图片描述

  • 面向对象的核心是对象二字,而对象的精髓在于整合,所有的程序都是由数据功能组成,因而编写程序的本质就是定义出一系列的数据,然后定义出一系列的功能来对数据进行操作。在学习”对象“之前,程序中的数据与功能是分离开的,在学习了“对象”之后,我们就有了一个容器,该容器可以盛放数据与功能,所以我们可以说:对象是把数据与功能整合到一起的产物,或者说”对象“就是一个盛放数据与功能的容器/箱子/盒子
    在这里插入图片描述

"""
在现实生活中 
	人					对象
	一群人			 人类

	狗				  对象
	一群狗      犬类
上述中的人类、犬类是用来描述什么的?
	就是用来描述多个对象'相同'特征的名词
		黄种人 黑种人 白种人都属于人类 但是彼此也有不同的特征
			类只能描述出公共的特征!!! 不同的特征应该由对象自己描述!!!
"""
ps:类其实也算对象>>>:一切皆对象

四、 类与对象的创建

  1. 在代码编程中是先有类才能有对象
  2. 先定义类 后产生对象
# 先定义类 后产生对象
# 学生类
class Student:
    # 学生类公共的数据
    school = '清华大学'
    # 学生类公共的功能
    def choose_course(self):
        print('学生选课功能')
"""类体代码无需调用就会执行 产生类的名称空间"""
"""
语法结构
class 类名:
    类体代码
1.class是定义类的关键字
2.类名类似于函数名 但是首字母推荐大写 用于区分 应该使用“驼峰体”
3.类体代码就是存放对象公共数据和功能的地方
    数据: 变量名 = 变量值
    功能: 函数
"""
  1. 查看名称空间的方法>>>:__dict__
print(Student.__dict__)                  # 返回值是一个字典
print(Student.__dict__['school'])        # 获取类中的属性
print(Student.__dict__['choose_course']) # 获取类中的属性
  1. 类获取数据和功能有一个简便的方式 : 句点符
print(Student.school)
print(Student.choose_course)
  1. 如何产生对象:类名加括号
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: # 类的命名应该使用“驼峰体”

    school='清华大学' # 数据

    def choose(self): # 功能
        print('%s is choosing a course' %self.name)

        类体最常见的是变量的定义和函数的定义,但其实类体可以包含任意Python代码,类体的代码在类定义阶段就会执行,因而会产生新的名称空间用来存放类中定义的名字,可以打印Student.__dict__来查看类这个容器内盛放的东西,如下:

print(Student.__dict__)
{..., 'school': '清华大学', 'choose': <function Student.choose at 0x1018a2950>, ...}

调用类的过程称为将类实例化,拿到的返回值就是程序中的对象,或称为一个实例

stu1=Student() # 每实例化一次Student类就得到一个学生对象
stu2=Student()
stu3=Student()

        如此stu1、stu2、stu3全都一样了(只有类中共有的内容,而没有各自独有的数据),想在实例化的过程中就为三位学生定制各自独有的数据:姓名,性别,年龄,需要我们在类内部新增一个__init__方法

class Student:
    school='清华大学'
    
    #该方法会在对象产生之后自动执行,专门为对象进行初始化操作,可以有任意代码,但一定不能返回非None的值
    def __init__(self,name,sex,age):
        self.name=name
        self.sex=sex
        self.age=age
        
    def choose(self): 
        print('%s is choosing a course' %self.name)

重新实例如下:

stu1=Student('小明','男',28)
stu2=Student('小红','女',18)
stu3=Student('小兰','男',38)
print(stu1.__dict__)  # {'name': '小明', 'sex': '男', 'age': 28}
print(stu2.__dict__)  # {'name': '小红', 'sex': '女', 'age': 18}
print(stu3.__dict__)  # {'name': '小兰', 'sex': '男', 'age': 38}

        单拿stu1的产生过程来分析,调用类会先产生一个空对象stu1,然后将stu1连同调用类时括号内的参数一起传给__init__方法,会产生对象的名称空间,同样可以用__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)
# 类调用类中函数 有几个参数就需要传几个参数
# 对象调用类中函数  会将当前调用的对象当做第一个参数自动传入

print(obj1.__dict__)  # {'name': 'jason', 'age': 18}
obj1.func()           # jason正在调用func方法
obj2.func()           # kevin正在调用index方法

'''所以应该能理解为什么类中所有的函数第一个参数都是self'''

请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

絵飛·的魚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值