面向对象

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

面向对象编程思想前戏

编写一个人狗大战小游戏
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)
print(p1,p2)
print(dog1,dog2)

# 狗咬人:
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):
     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)————————>狗调用了人的功能
要避免出现以上这种情况就要让人的数据与人的功能绑定,狗的1数据与狗的功能绑定,将人的攻击动作放在产生人的函数内,给人的数据绑定一个'person_attack' = person_attack。同理将狗的攻击动作放在产生狗的函数内,给狗的数据绑定一个'dog_attack' = dog_attact。
def get_person(name, gender, age, t_type, attack_val, life_val):
    def person_attack(person_obj, 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):
     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)
# 上述操作其实就是将数据与功能绑定,不再是所有的数据都可以调用任意的功能,也不是所有的功能都可以使用任意的数据
# 将数据与功能绑定(整合)到一起的操作就是面向对象编程的思想

编程思想

1.面向过程思想:将程序的执行,即分布操作,分布过程中解决问题,就是将复杂的问题拆分成多步
eg:注册,登录,结算,结算购物车
    注册:第一步获取用户名,第二步比对用户名数据
    
2.面向对象编程
核心就是“对象”二字,对象其实就是一个“容器”,将数据与功能整合到一起,只要是符合上述描述的事物都可以称之为是对象,人狗大战最后的函数内部含有数据和功能,可以称之为面向对象编程。模块文件内部含有数据和功能,也可以称之为面向对象编程
# Python中针对面向对象编程提供了专门的语法,识别度更多,编写更精简。
面向对象编程:有非常清晰的人物功能
# 面向过程编程与面向对象没有优劣之分,具体要结合实际情况,甚至很多时候两者混合在一起的,只不过在具体情况下思想占据的比例不同
# Python中一切皆对象

类与对象的概念

对象:数据与功能的结合体
类:即类别、种类,相当于诸多对象公有的特征(数据、功能)
类只能描述出公共的特征,不同的特征应该由对象自己搞定
# 类其实也算对象(一切皆对象)

类与对象的创建

# 在代码编程中先有类才能有对象(先定义类,后产生对象)
eg:# 学生类
    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_coures'])>>>>>>>获取类中的属性
"""类获取数据和功能有一个简便的方式>>>>>:句点符"""
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),obj就是对象本身
3.将创建好的对象自动返回

# 针对括号内第一个形参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)