面向对象引入
以小游戏人狗大战为例
步骤一:定义人与狗的数据
person = { 'name': '钢弹', 'age': 18, 'gender': 'male', 'p_type': '猛男', 'attack_val': 800, 'life_val': 99999 dog = { 'name': '龙傲天', 'd_type': '马犬', 'attack_val': 500, 'life_val': 100000 } """ 通过字典的形式,我们可以定义出所需要的人与狗的数据,但是如果我们这个游戏是回合制游戏,需要多个角色数据时呢 我们需要多次复制同样的数据,来满足游戏对角色的需求,那么以我们目前所学的知识,我们可以封装函数来完成 """
步骤二:封装函数产生数据
2.1 产生数据的函数
def create_person(name, age, gender, p_type, attack_val, life_val): person_dict = { 'name': name, 'age': age, 'gender': gender, 'p_type': p_type, 'attack_val': attack_val, 'life_val': life_val } return person_dict def create_dog(name, d_type, attack_val, life_val): dog_dict = { 'name': name, 'd_type': d_type, 'attack_val': attack_val, 'life_val': life_val } return dog_dict p1 = create_person('jason', 18, 'male', '猛男', 8000, 99999999) p2 = create_person('kevin', 28, 'female', '淑女', 100, 800) d1 = create_dog('小黑', '恶霸', 800, 900000) d2 = create_dog('小白', '泰迪', 100, 800000) print(p1, p2) print(d1, d2) """ 这样我们通过函数就完成了多个数据的产生,那么游戏就可以开始进行了,但在此之前,我们需要先定好游戏的规则,以代码的形式完成游戏流程 """
2.2 调用数据完成游戏流程的函数
def person_attack(person_dict, dog_dict): # 人攻击狗的函数 print(f"人:{person_dict.get('name')}准备揍狗:{dog_dict.get('name')}") dog_dict['life_val'] -= person_dict.get('attack_val') print(f"人揍了狗一拳 狗掉血:{person_dict.get('attack_val')} 狗剩余血量:{dog_dict.get('life_val')}") def dog_attack(dog_dict, person_dict): # 狗攻击人的函数 print(f"狗:{dog_dict.get('name')}准备咬人:{person_dict.get('name')}") person_dict['life_val'] -= dog_dict.get('attack_val') print(f"狗咬了人一口 人掉血:{dog_dict.get('attack_val')} 人剩余血量:{person_dict.get('life_val')}") person_attack(p1, d1) # 运行游戏 dog_attack(d2, p2) """ 人:jason准备揍狗:小黑 人揍了狗一拳 狗掉血:8000 狗剩余血量:892000 狗:小白准备咬人:kevin 狗咬了人一口 人掉血:100 人剩余血量:700 这么看来我们的游戏流程已经完成了但是... """ person_attack(d1, p1) dog_attack(p1, d2) """ 人:小黑准备揍狗:jason 人揍了狗一拳 狗掉血:800 狗剩余血量:99999199 狗:jason准备咬人:小白 狗咬了人一口 人掉血:8000 人剩余血量:792000 当我们反过来输入信息后,狗变成了人,人变成了狗,数据发生了混乱 函数的调用并不明确那个函数是对应哪些数据才可以调用,这时候就要步入新的阶段 >>>:面向对象 """
面向对象核心思路
那么我们如何来实现人只可以使用人的攻击函数,狗只可以使用狗的攻击函数呢?
——数据与函数绑定
def get_person(name, age, gender, p_type, attack_val, life_val): # 产生人的函数(功能) def person_attack(person_dict, dog_dict): print(f"人:{person_dict.get('name')}准备揍狗:{dog_dict.get('name')}") dog_dict['life_val'] -= person_dict.get('attack_val') print(f"人揍了狗一拳 狗掉血:{person_dict.get('attack_val')} 狗剩余血量:{dog_dict.get('life_val')}") # 表示人的信息(数据) person_dict = { 'name': name, 'age': age, 'gender': gender, 'p_type': p_type, 'attack_val': attack_val, 'life_val': life_val, 'person_attack': person_attack } return person_dict def get_dog(name, d_type, attack_val, life_val): def dog_attack(dog_dict, person_dict): print(f"狗:{dog_dict.get('name')}准备咬人:{person_dict.get('name')}") person_dict['life_val'] -= dog_dict.get('attack_val') print(f"狗咬了人一口 人掉血:{dog_dict.get('attack_val')} 人剩余血量:{person_dict.get('life_val')}") dog_dict = { 'name': name, 'd_type': d_type, 'attack_val': attack_val, 'life_val': life_val, 'dog_attack': dog_attack } return dog_dict person1 = get_person('jason', 18, 'male', '猛男', 8000, 99999999) dog1 = get_dog('小黑', '恶霸', 800, 900000) person1.get('person_attack')(person1, dog1) """ 人:jason准备揍狗:小黑 人揍了狗一拳 狗掉血:8000 狗剩余血量:892000 我们通过第一层函数,实现了角色信息的生成,由于函数内部的名称只能在内部调用,所以我们将人与狗各自的攻击函数放入到第一层函数中,并把函数名作为键值对的值存放在用户的字典中,那么当我们得到返回的字典时,就只需要将对应的攻击函数取出来即可实现函数调用,同时我们也实现了功能与数据的绑定,这也就是面向对象的核心 """
编程思想
所谓的编程思想,或者说编程方式,只有两种——面向过程与面向对象
面向过程,顾名思义,更注重过程,放到编程来讲,面向过程是当我们看到需求时,要将需求拆分成各个组成部分,就以我们之前写的ATM为例,当我们需要登录时,我们需要先去校验用户是否存在,然后验证用户输入的密码是否正确,需要一步步完成各个组成部分,将每部分功能都写出来,主要的侧重点在于拆分与完成各组成部分的过程,并且随着每个部分的深入,问题的解决越来越简单
而面向对象,则需要引用到python中一切皆对象的概念,对象即容器,可以存放数据与方法的容器,我们可以理解为容器中既有数据值,又有函数,就像我们常用的列表,字典,他们既有数据值,也有内置方法,这就是容器,面向对象编程时,我们不需要再去一步步拆分,只需要创建好对象,任由其在被需要的时候调用,至于怎么发展就不是我们需要考虑的事情了
面向对象之类与对象
对象就是数据和方法的结合体,而类是在多个对象需要被定义时,在这些对象中包含的相同的数据和方法,我们就可以用类一次性接收,不需要在每个对象中重复编写
任何事物只有在数量达到一定程度后,根据他们相同的特征划分为相同的相同的类,比如人类,犬类,类是一个宽泛的概念,代表着这个类中每个个体所具有的共性
在现实生活中,只有当个体的对象达到一定数量后才会产生类的概念,而在编程中,如果需要产生对象时,我们需要先定义出类,才可以从这个类中产生我们需要的对象
类与对象的创建
面向对象并不是真正意义上的新技术,而是为了作为区分设计的新的语法结构,在python中,一定要先定义类,才可以用类产生对象
类的语法结构
class 类名: '''代码注释''' 对象公共的数据 对象公共的功能 """ 1.class是定义类的关键字 2.类名的命名与变量名几乎一致,需要注意的时候首字母推荐大写用于区分 3.数据:变量名与数据值的绑定,功能(方法)其实就是函数 4.类与对象,对象才是关键,这也是面向对象编程的关键所在 """
类的定义与调用
类在定义阶段会执行类体代码,但是产生对象仅仅属于类的局部名称空间,外界无法直接调用
以定义选课系统为例
# 需求:清华大学学生选课系统 # 定义类 class Student: # 对象公共的数据 school_name = '清华大学' # 对象公共的功能 def choice_course(self): # self 代表类的实例,self在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数,在某种意义上,self即类中产生的对象本身 print('学生选课功能') # 查看名称空间 print(Student.__dict__) # __dict__只是python提供的一种查看名称空间的方式,并不意味着类就是字典,只不过是这个名称空间以字典的形式呈现 print(Student.__dict__.get('school_name')) print(Student.__dict__.get('choice_course')) '''在面向对象中 类和对象访问数据或者功能 可以统一采用句点符''' print(Student.school_name) print(Student.choice_course) # 类只有在调用时才会产生对象 '''类名加括号就会产生对象,并且每执行一次都会产生一个全新的对象''' obj1 = Student() # 变量名obj1接收类名加括号之后的返回值(结果) obj2 = Student() obj3 = Student() print(obj1, obj2, obj3) print(obj1.__dict__) # 在没有定义属性前,类的名称空间中是空的 print(obj2.__dict__) print(obj3.__dict__) print(obj1.school_name) # 当我们通过.的方式调用类中的公共变量名时,会直接输出该变量名绑定的数据值 print(obj2.school_name) print(obj3.school_name) Student.school_name = '家里蹲大学' # 我们也可以通过按照字典改值的方式修改类中的公共数据 print(obj1.school_name) print(obj2.school_name) print(obj3.school_name) '''数据和功能,也可以统称为属性,数据就是类中存放的绑定给对象的属性名,功能就类中存放的可供对象使用的方法'''
对象独有的数据
就像人类同样是在人这一个大类中,个体却各有差异一样,类中的对象也有其独有的数据
以选课系统为例
class Student: # 对象公共的数据 school_name = '清华大学' # 对象公共的功能 def choice_course(self): print('学生选课功能') obj1 = Student() obj2 = Student() '''推导流程1:每个对象手动添加独有的数据''' print(obj1.__dict__) obj1.__dict__['name'] = 'jason' obj1.__dict__['age'] = 18 obj1.__dict__['hobby'] = 'study' print(obj1.__dict__) print(obj1.name) print(obj1.age) print(obj1.hobby) print(obj2.__dict__) obj2.__dict__['name'] = 'kevin' obj2.__dict__['age'] = 28 obj2.__dict__['hobby'] = 'music' print(obj2.__dict__) print(obj2.name) print(obj2.age) print(obj2.hobby) # 当我们使用类中自带的方法一个一个添加数据时,代码需要不断地重复,这种情况下,我们就需要用到函数 '''推导流程2:将添加对象独有数据的代码封装成函数''' def init(obj, name, age, hobby): obj.__dict__['name'] = name obj.__dict__['age'] = age obj.__dict__['hobby'] = hobby stu1 = Student() stu2 = Student() init(stu1, 'jason', 18, 'music') init(stu2, 'kevin', 29, 'read') print(stu1.__dict__) print(stu2.__dict__) # 当我们函数封装完毕后,我们在添加数据时,这个函数不只有现在的学生对象可以用 # 其他类产生的对象也可以用,那么为了实现只有当前类产生的对象可以采用这种方法添加数据 # 我们只能将这个函数放到类中 '''推导流程3:给学生对象添加独有数据的函数只有学生对象有资格调用''' class Student: # 对象公共的数据 school_name = '清华大学' # 专门给学生添加独有数据的功能 def init(obj, name, age, hobby): obj.__dict__['name'] = name obj.__dict__['age'] = age obj.__dict__['hobby'] = hobby # # 对象公共的功能 def choice_course(self): print('学生选课功能') stu1 = Student() Student.init(stu1, 'jason', 18, 'music') stu2 = Student() Student.init(stu2, 'kevin', 29, 'read') print(stu1.__dict__, stu2.__dict__) # 当我们将函数放到类中之后,每次添加数据还需要再调用init函数,那么是不是可以更加简便 '''推导步骤4:init方法变形''' class Student: # 对象公共的数据 school_name = '清华大学' # 专门给学生添加独有数据的功能 __init__在类产生对象的过程中自动触发 def __init__(obj, name, age, hobby): obj.__dict__['name'] = name obj.__dict__['age'] = age obj.__dict__['hobby'] = hobby # 对象公共的功能 def choice_course(self): print('学生选课功能') stu1 = Student('jason', 18, 'read') print(stu1.__dict__) print(stu1.name) print(stu1.school_name) # 当这一步完成后,我们可以省去调用函数这一步,但是还是需要在类中使用obj.__dict__[]的方法来添加数据,那么这个时候,self就派上用场了,在这个时候,self代表的就是类产生的对象本身 '''推导步骤5:变量名修改''' class Student: # 对象公共的数据 school_name = '清华大学' # 专门给学生添加独有数据的功能 类产生对象的过程中自动触发 def __init__(self, name, age, hobby): self.name = name # self.__dict__['name'] = name self.age = age self.hobby = hobby # 对象公共的功能 def choice_course(self): print('学生选课功能') stu1 = Student('jason', 18, 'read') print(stu1.name) print(stu1.school_name) # 当self产生作用后,那么我们也就可以用self加句点符来添加相应的数据,类体代码的兼容性也会更强
对象独有的功能
参照上述方法,我们也可以得出,对象也可以有自己独有的功能或函数
class Student: # 对象公共的数据 school_name = '清华大学' # 专门给学生添加独有数据的功能 类产生对象的过程中自动触发 def __init__(self, name, age, hobby): self.name = name # self.__dict__['name'] = name self.age = age self.hobby = hobby # 对象公共的功能 def choice_course(self): print(f'学生{self.name}正在选课') stu1 = Student('jason', 18, 'music') stu2 = Student('kevin', 28, 'read') # 1.直接在全局定义功能 该函数就不是学生对象独有的了 def eat(): print('吃东西') stu1.eat = eat print(stu1.__dict__) stu1.eat() # 2.只能将函数放在类中 但是类中的函数又是对象公共的 '''定义在类中的功能,默认就是绑定给对象使用的,哪个对象来调用,哪个对象就是主导''' Student.choice_course(123) # 类调用需要自己传参数 stu1.choice_course() # choice_course(stu1) 对象调用会自动将对象当做第一个参数传入 stu1.choice_course() stu2.choice_course() # 当self产生作用时,对象本身就会被当作参数传递到该共功能中 # 对象修改数据值 stu1.name = 'tony' # 当点的名字已经存在的情况下 则修改对应的值 # 对象新增数据值 stu1.pwd = 123 # 当点的名字不存在的情况下 则新增数据 print(stu1.__dict__)
PS:面向对象编程就像为我们搭建了一个工具箱,而其中不同的函数就相当于不同类型的工具,我们在取用工具时,我们就是不同的对象,当我们使用工具时,工具会与我们绑定,这个时候这个工具就是我们的专用工具,也就是对象的独有功能,当我们使用完工具放回工具箱后,谁再来用,怎么用跟我们就关系不大了,这样的好处就是工具不会丢,这样理解,类与对象的存在也正是为了程序有更好的可拓展性和更高的兼容性
原文地址:http://www.cnblogs.com/lf17603472426/p/16852539.html