面向对象编程思想 OOP
什么是面向对象
面向对象是一种编程思想,是前辈们总结出的经验,指导程序员如何编写出更好的程序 ,
核心是对象,程序就是一系列对象的集合, 程序眼负责调度控制这些对象来交互着完成任务:
案例:1 把大象装进冰箱 ?
面向过程:
1.打开冰箱
2.装入大象
3.关闭冰箱
面向对象:
找个具备装大象的技能的对象
在面向对象中程序员的角度发生改变,从具体的操作者变成了指挥者;
强调:对象不是凭空产生的,需要我们自己设计
案例:
西天取经
如来有一堆破书要传出去,他没有自己干,而是找了五个对象帮他去干,
如来只要负责控制调度的对象即可 ,
如果某个对象发生变化,也不会影响其他的对象 , 扩展性
面向对象的三大优点
1.扩展性
2.灵活性
3.重用性
缺点:
1.程序的复杂度提高了
2.无法准确预知结果
使用场景
对扩展性要求较高的程序 ,通常是直接面向 用户的,例如:qq,微信
面向过程编程思想
关注的核心是过程,过程是就是一步一步的执行步骤,既先干啥在干啥
优点:逻辑清晰 , 复杂问题简单化,流程化
缺点: 扩展性差,可维护性差
使用场景:
对扩展性要求较低的程序例如:系统内核,git,计算器
记住:不是所有程序都要面向对象,得分析具体需求
类和对象
这是OOP中的最核心的两个概念
类
既类型,类别 ,是一种抽象概念
是一系列具备相同特征和相同行为的对象的集合
对象
就是具体存在的某个事物,具备自己的特征和行为
对象就是特征和技能的结合体
类和对象的关系
类包含一系列对象
对象属于某个类
在生活中是先有对象再有类
而在程序中是先有类才能有对象,我们必须先告诉计算机这类的对象有什么特征有什么行为
总结出一个结论:在使用面向对象编程时,第一步就是思考需要什么样的对象,对象具备什么样的特征和行为,从而根据 这些信息总结出需要的类型
创建类和对象
定义类的语法
class 类的名称:
# 类中的内容 描述属性和技能
#描述属性用变量
#描述行为用函数
#类名称 书写规范 首先是见名知意 名称是大驼峰命名法
#驼峰就是单词首字母大写 , 大驼峰是第一个字母大写,小驼峰是第一个字母小写
创建对象的语法:
class Person:
pass
#创建对象
p = Person()
属性的写法:
属性可以写在类中
类中的属性,是所有对象公共的
也可以写在对象中
对象中的属性,是每个对象独特的(不一样的)
如果类中和对象中存在同样的属性,先访问对象 如果没有在访问类
练习: 描述一个老师类 需要包含 一个公共属性和 一个独特的属性
class Teacher: school = "oldboy" t1 = Teacher() t1.name = "jack" t1.age = 28
属性的增删改查
增加属性
对象变量名称.属性名称 = 属性值
删除属性
del 对象的变量名称.属性名称
修改
对象.属性 = 新的值
查看属性 访问的是对象的所有属性
print(对象.__dict__)
访问对象的类信息
print(对象.__class__)
init方法
叫做初始化方法,本质上就是一个函数
特点1: 当实例化 对象时,会自动执行init方法
特点2:会自动将对象作为第一个参数传入,参数名称位self ,self可以是别的名字,但不建议改
功能:用户给对象赋初始值
练习:创建一个类具备几个属性,通过初始化方法来给他设置属性
class Dog: def __init__(self,kind,color,age): self.kind = kind self.color = color self.age = age d1 = Dog("二哈","黑白",1) d1 = Dog("泰迪","棕色",2)
注意:该函数不能有任何返回值/.... 只能是None 规定如此..
对象的精髓就是讲数据和处理数据的函数整合到一起 ,这样一来拿到一个对象就同时拿到了需要处理的数据以及处理数据的函数
对象的绑定方法
默认情况下类中的方法都是对象绑定方法
其特殊之处在于,
当使用对象调用该函数时会自动传入对象本身,作为第一个参数
当使用类名来调用时他就是一个普通函数,有几个参数就得传几个参数
练习:写一个学生类,具备一个打招呼的技能 要能输出自己的名字信息
class Student: def __init__(self,name): self.name = name def say_hi(self): print("hello my name is %s" % self.name)
类绑定方法
类绑定方法用@classmethod来装饰
特殊之处:不管用类还是对象调用,都会自动传入类本身,作为第一个参数
什么时候绑定给对象:当函数逻辑需要访问对象中的数据时
什么时候绑定给类:当函数逻辑需要访问类中的数据时
非绑定方法
或叫做静态方法,就是即不需访问类的数据,.也不需要访问对象的数据
语法:@staticmethod
不常用
小练习:
'''''' import random import time ''' 需求设计王者荣耀中的英雄类,每个英雄对象可以对其他英雄对象使用技能 具备以下属性 英雄名称,等级,血量 和Q_hurt,W_hurt,E_hurt 三个属性,表示各技能的伤害量 具备以下技能 Q W E 三个技能都需要一个敌方英雄作为参数,当敌方血量小于等于0时角色死亡 代码实现: ''' class Hero: def __init__(self,name,level,blood,Normal_hurt,Q_hurt,W_hurt,E_hurt): self.name = name self.level = level self.blood = blood self.Normal_hurt = Normal_hurt self.Q_hurt = Q_hurt self.W_hurt = W_hurt self.E_hurt = E_hurt # lcs = locals() # lcs.pop('self') # self.__dict__.update(lcs) def attack(self,enemy): enemy.blood = enemy.blood - self.Normal_hurt print('%s 使用普通攻击对 %s 造成 %s 剩余血量%s'%(self.name,enemy.name,self.Normal_hurt,enemy.blood)) if enemy.blood <= 0: print('%s 被 %s 使用普通攻击击杀了'%(enemy.name,self.name)) def Q(self, enemy): enemy.blood = enemy.blood - self.Q_hurt print('%s 使用Q技能对 %s 造成 %s 剩余血量%s' % (self.name, enemy.name, self.Q_hurt, enemy.blood)) if enemy.blood <= 0: print('%s 被 %s 使用Q技能击杀了' % (enemy.name, self.name)) def W(self, enemy): enemy.blood = enemy.blood - self.Q_hurt print('%s 使用W技能对 %s 造成 %s 剩余血量%s' % (self.name, enemy.name, self.W_hurt, enemy.blood)) if enemy.blood <= 0: print('%s 被 %s 使用W技能击杀了' % (enemy.name, self.name)) def E(self, enemy): enemy.blood = enemy.blood - self.E_hurt print('%s 使用E技能对 %s 造成 %s 剩余血量%s' % (self.name, enemy.name, self.E_hurt, enemy.blood)) if enemy.blood <= 0: print('%s 被 %s 使用E技能击杀了' % (enemy.name, self.name)) h1 = Hero('韩信',15,8000,1500,1000,2500,2000) h2 = Hero('廉颇',15,12000,200,500,700,1500) h3 = Hero('百里守约',15,7000,1500,0,3000,2500) h4 = Hero('小乔',15,5000,700,3000,2500,5000) def random_hero(heros): hero_index = random.randint(1, len(heros)) return heros[hero_index] while True: # # 把所有的攻击方法装到字典里 为了随机取出一个 funcs = {1: Hero.Q, 2: Hero.W, 3: Hero.E, 4: Hero.attack} func_index = random.randint(1, 4) func = funcs[func_index] # 把所有的英雄方法装到字典里 为了随机取出一个 heros = {1: h1, 2: h2, 3: h3, 4: h4} hero = random_hero(heros) # 剩余的英雄们 other_heros = {} new_index = 1 for k, v in heros.items(): if v != hero: other_heros[new_index] = v new_index += 1 # 从剩余的英雄中随机挑出一个英雄来挨打 enemy = random_hero(other_heros) # 打他 func(hero, enemy) if enemy.blood <= 0: break time.sleep(0.5)