python编程思想,类与对象

本章内容

        • 编程思想

        • 类与对象

 

编程思想


面向对象编程思想前戏

我们以人狗大战小游戏为例子。

# 第一步:描述人和狗的方式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
}

一个一个的描述,如果有很多个人或狗需要描述,代码太冗余了,所以我们可以把描述封装成函数。

# 封装成函数 减少代码冗余
# 描述人的函数
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)  # 狗:小白 咬了人:jason 一口 人掉血:50 剩余血量:950
print(p1)  
# 人锤狗
person_attack(p2, dog1)  # 人:kevin 锤了狗:小黑 一下 狗掉血:5 剩余血量:495
print(dog1)

那有没有想过,如果人调用了狗的攻击动作,狗调用了人的攻击动作,是不是就乱套了!

print(dog_attack(p1, dog1))  # 狗:jason 咬了人:小黑 一口 人掉血:800 剩余血量:-300
print(person_attack(dog2, p2))  # 人:小白 锤了狗:kevin 一下 狗掉血:50 剩余血量:50

如何做到只有人可以调用人的攻击动作 狗调用狗的攻击动作?其实就是想让人的数据跟人的功能绑定 狗的数据跟狗的功能绑定。

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)  # 人:jason 锤了狗:小黑 一下 狗掉血:800 剩余血量:-300
dog1['dog_attack'](dog1,p2)  # 狗:小黑 咬了人:kevin 一口 人掉血:300 剩余血量:-200

上述操作其实就是将数据与功能进行绑定,不是所有的数据都可以调用任意的功能,从而引出下面的面向对象编程。

 

编程思想

1.面向过程编程

将程序的执行流程化 ,分步操作,分步的过程中解决问题。
eg:注册,登录,购物车结算,修改密码等。
过程可以理解成是流水线,面向过程编程可以理解成是在创建一条流水线。

2.面向对象编程

核心就是'对象'二字 ,对象其实就是一个"容器" 将数据与功能整合到一起。
就像上方人狗大战那样,将人与人的工作绑定在一起的容器称为对象。
只要是符合上述描述的事物都可以称之为是对象!!!

面向过程与面向对象两者没有优劣之分 ,具体要结合实际情况。甚至很多时候两者是混合在一起的!!! 思想占据的比例不同而已

 

类与对象


类与对象的概念

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

PS:对象是一个个体,类是一个群体。类是来描述多个对象相同的特征。
eg:黄种人,黑种人,白种人都属于人类,但是彼此也有不同的特征,类只能描述出公共的特征!!! 不同的特征应该由对象自己描述!!!

类与对象的创建

在代码编程中是先有类才能有对象,所有先定义类,后产生对象。

语法结构
class 类名:
    类体代码
1.class是定义类的关键字
2.类名类似于函数名 但是首字母推荐大写 用于区分
3.类体代码就是存放对象公共数据和功能的地方
    数据: 变量名 = 变量值
    功能: 函数

eg:先定义一个学生类---类体代码无需调用就会执行,产生类的名称空间

class Student:
    # 学生类公共的数据
    school = '清华大学'
    # 学生类公共的功能
    def choose_course(self):
        print('学生选课功能')
# 查看名称空间的方法>>>:__dict__ 
print(Student.__dict__)  # 返回值是一个字典 {'__module__': '__main__', 'school': '清华大学',...}
print(Student.__dict__['school'])  # 获取类中的属性   清华大学
print(Student.__dict__['choose_course'])  # 获取类中的属性   <function Student.choose_course at 0x0000028D37F5CC80>
# 句点符---类获取数据和功能
print(Student.school)  # 清华大学
print(Student.choose_course)  # <function Student.choose_course at 0x0000028D37F5CC80>

产生对象:类名加括号

obj1 = Student()  # 类名加括号就是在产生一个对象
obj2 = Student()
# 产生对象后就可以通过对象加句点符去调用类里的数据和函数功能
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()  # 1目前对象没有自己独有的属性
# 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__的第一个参数就是对象本身
          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)  # <__main__.Student object at 0x000002459FF267F0>
obj2 = Student('kevin', 28)
# 类调用类中函数 有几个参数就需要传几个参数
# Student.func(11,22)
# 对象调用类中函数  会将当前调用的对象当做第一个参数自动传入
obj1.func()  # jason正在调用func方法
obj2.func()  # kevin正在调用func方法
print(obj1.func)   # <bound method Student.func of <__main__.Student object at 0x0000012F7136AC18>>
print(obj2.index)  # <bound method Student.index of <__main__.Student object at 0x0000012F7136AC88>>

 

posted @ 2022-04-06 20:33  早安_1207  阅读(74)  评论(0)    收藏  举报
返回顶端