Day 20 初识面向对象
1.面向对象的概念 (OOP): 面向对象就是一种编程思想
1.面向对象编程思想:核心就是对象,程序就是一系列对象的集合,程序来负责调控这些对象来交互完成任务
三大优点:1:扩展性强 程序员角度由操作者变为指挥者,可以找对象帮忙完成某些功能,而对象不是凭空产生的.需要我们设计
2: 灵活性强 如果某个对象发生变化,也不会影响其他的对象
3: 重用性强 可以让多个对象拥有同一个功能.无需逐个添加
缺点: (1) 程序的复杂度提高 (2) 无法准确的预知结果
使用场景: 对扩展性要求较高的程序,通常是直接面向用户的,如qq.微信
2.面向过程编程思想 : 核心是过程,一步一步的执行步骤,先干什么再干什么
优点: 逻辑清晰,将复杂的问题简单化,流程化
确定 : 扩展性差,可维护性差 ,一步改动有可能整个程序都得改动
使用场景: 对于扩展性要求较低的程序:如系统内核,git,计算器
2.类和对象的概念: 面向对象中最核心的两个概念,即类,对象
1.类 : 就是类型,类别,一种抽象的概念,是一系列具备相同特征和行为的对象的集合,并不是真实存在的
2.对象: 类型里的一个个体,如人类中某个指定的人,是具体存在的事物,具备自己的特征与行为 , 对象就是特征与技能的结合体
3.对象与类的关系:类包含一系列对象,对象属于某个类,在生活中现有对象在有类,而在程序中先有类才能有对象,我们必须先告诉计算机这类对象有什么特征和行为
4.结论: 在使用面向对象编程时,第一步要先思考需要什么杨的对象,对象具备什么样的特征和i行为,从而根据这些信息总结出需要的类型
3.如何创建类与对象
1.定义类的语法:
class 类的名称: # 类中的内容 描述属性和技能 #描述属性用变量 #描述行为用函数 #类名称 书写规范 首先是见名知意 名称是大驼峰命名法 #驼峰就是单词首字母大写 , 大驼峰是第一个字母大写,小驼峰是第一个字母小写
2.创捷对象的语法:
对象 = 类名()
3.例:
class Stu: # 定义一个Stu类 pass student = Stu() # 调用Stu类创建一个student对象,也称作实例化对象
4.如何设计属性 : 属性可以写在类中,类中的属性,是所有对象公共的,也可以写在对象中,对象中的属性,是每个对象独有的
class Stu: addr = '天津' # 定义添加属性 del addr # 删除Stu类的addr属性 addr = '天津' addr = "上海" # 将addr属性改变 s1 = Stu() print(s1.addr) # 访问上海 s1.name = '小红' # 为学生类对象s1添加独有属性name print(s1.name) # 小红 print(s1.__class__) # 访问对象的类信息 print(s1.__dict__) # 访问对象的所有属性
5.属性的查找顺序 : 如果类中和对象中存在同样的属性,先访问对象 如果没有在访问类
class Stu: addr = "上海" # 将addr属性改变 s1 = Stu() print(s1.addr) # 上海 s1.addr = '北京' print(s1.addr) # 北京
6.初始化方法: 类中的__init__方法,也称作初始化方法,本质就是一个函数
特点:(1) 当实例化对象时,会自动执行__init__方法
(2) 会自动将对象作为第一个参数传入,参数名为self,self可以是别的名字,但不建议修改
功能: 用户给对象赋初始属性
class Stu: def __init__(self,name,age,addr): self.name = name self.age = age self.addr = addr s1 = Stu('小明',18,'上海') print(s1.name, s1.age, s1.addr ) # 小明 18 上海
# 小方法,当初始属性过多时 class Stu: def __init__(self,name,age,addr): lcs = locals() lcs.pop('self') self.__dict__.update(lcs) s1 = Stu('小明',18,'上海') print(s1.name, s1.age, s1.addr ) # 小明 18 上海
7. 绑定方法与不绑定方法
1: 对象绑定方法: 默认的.当使用对象调用此函数时会自动传入对象本身,作为第一个参数
2: 类绑定方法: 不管时用类还是对象调用,都会传入类本身作为第一个参数 @classmethod 装饰
3: 不绑定方法,又称为静态方法 : 相当于定义在类外面的方法 @staticmethod装饰
4. 使用场景: 当函数逻辑需要访问到对象中的数据时使用对象绑定方法,当函数逻辑需要访问到类中的数据时使用类绑定方法,当函数逻辑既不需要访问对象的数据也不需要类中的数据时使用不绑定方法
class Stu: school = 'oldboy' def __init__(self,name,age,school): self.name = name self.age = age self.school = school @classmethod def talk(cls): print(f"来自{cls.school}的") s1 = Stu('小明',15,'你猜') # Stu.talk() # s1.talk() # 不添加类方法 来自你猜的 s1.talk() # 添加后的 来自oldboy的
7. 序列化对象练习:
""" 练习:为学生类添加一个save方法 一个get方法 save是将对象存储到文件中 get是从文件中获取对象 """ import pickle class Stu: def __init__(self,name): self.name = name def save(self): with open(f'{self.name}.pickle',"wb") as f: pickle.dump(self,f) @staticmethod # 静态方法 def get(name): with open(f'{name}.pickle',"rb") as f: obj = pickle.load(f) return obj s1 = Stu('xiaoming') # s1.save() s2 = Stu.get('xiaoming') print(s2.name)
8. 对象交互练习
class Hero: def __init__(self,name,level,hp,q_hurt,w_hurt,e_hurt): self.name = name self.level = level self.hp = hp self.q_hurt = q_hurt self.w_hurt = w_hurt self.e_hurt = e_hurt def q(self,to_name): to_name.hp -= self.q_hurt print(f"{self.name}对{to_name.name}造成了{self.q_hurt}伤害,{to_name.name}剩余{to_name.hp}血") def w(self,to_name): to_name.hp -= self.w_hurt print(f"{self.name}对{to_name.name}造成了{self.w_hurt}伤害,{to_name.name}剩余{to_name.hp}血") def e(self,to_name): to_name.hp -= self.e_hurt print(f"{self.name}对{to_name.name}造成了{self.e_hurt}伤害,{to_name.name}剩余{to_name.hp}血") xiaoqiao = Hero('小乔',10,600,50,100,150) noc = Hero('梦魇',15,500,200,400,600) choice_list = [xiaoqiao,noc] name_list = [xiaoqiao.name, noc.name] func_dict = { 'q' : Hero.q, 'w' : Hero.w, 'e' : Hero.e } while 1: for index,name in enumerate(name_list): print(index,name) choice = int(input("请根据序号选你要操作的英雄")) to_name = int(input("请根据序号选你要针对的英雄")) skill = input("请输入你要使用的技能") if skill not in func_dict: continue else: func_dict[skill](choice_list[choice],choice_list[to_name]) if choice_list[to_name].hp <= 0: print(f"{choice_list[to_name].name}死亡,游戏结束") break