day 22 - 1 面向对象
面向对象
字典实现人狗大战
#定义角色 def Person(name,hp,aggr,sex): person = { 'name':name, 'hp':hp, 'aggr':aggr, 'sex':sex } return person def Dog(name,hp,aggr,kind): dog = { 'name':name, 'hp':hp, 'aggr':aggr, 'kind':kind } return dog
#定义技能 #打 def attack(person,dog): dog['hp'] -= person['aggr'] print('%s损失了%s的血量'%(dog['name'],person['aggr'])) #咬 def bite(dog,person): person['hp'] -= dog['aggr'] print('%s损失了%s的血量'%(person['name'],dog['aggr']))
#print(Person('new',100,2,'不祥')) #print(Dog('二哈',100,3,'taddy')) man = Person('雷诺',100,2,'不祥') #实例化 dogs = Dog('二哈',100,3,'taddy') bite(dogs,man) print(man)
这样会出现一个问题,就是把角色搞混
我们把技能封装到任务所属的函数中,这个就不容易把任务关系搞混了
def Person(name,hp,aggr,sex): person = { 'name':name, 'hp':hp, 'aggr':aggr, 'sex':sex } def attack(dog): dog['hp'] -= person['aggr'] print('%s损失了%s的血量'%(dog['name'],person['aggr'])) person['attack'] = attack return person def Dog(name,hp,aggr,kind): dog = { 'name':name, 'hp':hp, 'aggr':aggr, 'kind':kind } def bite(person): person['hp'] -= dog['aggr'] print('%s损失了%s的血量'%(person['name'],dog['aggr'])) dog['bite'] = bite return dog man = Person('new',100,2,'不祥') dogs = Dog('二哈',100,3,'taddy') man['attack'](dogs) #然后我们就可以这样来调用 Person 函数中的 attack 函数 dogs['bite'](man)
简单小结:
Dog 函数和 Person 函数 都是定义了一类事物
直到调用了函数,赋值了之后才真的有了一个实实在在的人或狗
代码精简了 方便增加人物 方便修改 人物更加规范 —— 人模子
面向对象编程
所谓模子 就是 类 抽象的 我能知道有什么属性 有什么技能 但不能知道属性具体的值
人 屋子 就是对象 有具体的值,属性和技能都是根据类规范的
面向过程 VS 面向对象
面向过程的程序设计的核心是过程(流水线式思维)
优点是:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可
缺点是:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。
应用场景:一旦完成基本很少改变的场景,著名的例子有 Linux 內核,git,以及Apache HTTP Server等
面向对象的程序设计的
优点是:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
缺点:可控性差,无法像面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现,一刀砍死3个人,这个游戏就失去平衡。
应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方
自定义类
#定义 class 类名: 属性 = 'a' #查看 print(类名.属性) # 类名的作用 就是操作属性 查看属性
我们来看一个例子
class Person: # 类名 def __init__(solf,*args): # 初始化方法,self是对象,是一个必须传的参数 solf.name = args[0] # self 就是一个可以存储很多属性的大字典 solf.hp = args[1] # 而往字典里添加属性的方式发生了一些变化 solf.aggr = args[2] solf.sex = args[3] per = Person('小强',100,3,'不祥') print(per) #返回的是一个内存地址 print(per.name) #查看属性值 print(per.hp) #查看属性值 print(per.aggr) #查看属性值
调用类中的方法
#调用类中的方法 class Person: count = 'China' # 创造了一个只要是这个类就一定有的属性,这个是类拥有的 而不是属性 # 类属性 静态属性 def __init__(self,*args):# 初始化方法 self.name = args[0] self.hp = args[1] self.aggr = args[2] self.sex = args[3] def run(self,n): #定义了一个方法,一般情况下必须传 self 参数,且必须写在第一个 #后面还可以传其他参数,是自由的 print('%s跑跑跑,跑了%s公里'%(self.name,n)) ##2.接收参数 per = Person('小强',100,3,'不祥') print(Person.__dict__) #可以看到 Person 方法中有 run 这个函数(#查看所有属性) print(Person.run) #为一个内存地址 Person.run(per,6) #此处为什么是 per,因为在赋值使用 Person 函数后 self 的值返回给了 per #per.run() #另一种简便方法 对象名 + 方法名 与 Person.run(per) 等价 per.run(5) ##1.传值 print(per.count) #获取静态属性
类的内容查看、修改、添加
#接上 #对类的内容查看、修改、添加 print(Person.__dict__) #得到的是类中存储的所有名字 print(Person.__dict__['count']) #可以通过 __dict__ 使用字典的方式操作 print(per.__dict__) #得到的 per 所有属性 print(per.__dict__['name']) per.__dict__['name'] = '小吼' #可以查看也可以修改 print(per.__dict__['name']) print(per.name) per.name = '鸟人' #不过一般通过属性来修改 print(per.name) per.age = 49 #增加 print(per.__dict__)
简单小结:
对象 = 类名()
过程:
类名() 首先 会创造出一个对象,创建了一个self变量
调用 init 方法,类名括号里的参数会被这里接收
执行 init 方法
返回 self
对象能做的事:
查看属性
调用方法
__dict__ 对于对象的增删改查操作都可以通过字典的语法进行
类名能做的事:
实例化
调用方法 : 只不过要自己传递 self 参数
调用类中的属性,也就是调用静态属性
__dict__ 对于类中的名字只能看 不能操作 比如:修改 count,报错
接着我要切入主题了
使用类来完成我们最初的游戏:人狗大战
#大致如下 class Person: def __init__(self,name,hp,aggr,sex): self.name = name self.hp = hp self.aggr = aggr self.sex =sex def attack(self,dog): dog.hp -= self.aggr print('%s 损失了 %s 点 hp'%(dog.name,self.aggr)) class Dog: def __init__(self,name,hp,aggr,kind): self.name = name self.hp = hp self.aggr = aggr self.kind = kind def bite(self,person): person.hp -= self.aggr self.hp -= person.aggr print('%s 损失了 %s 点 hp'%(person.name,self.aggr)) if person.hp < 0: print('%s 失血过多战败,%s 剩余 %s 点 HP'%(person.name,self.name,self.hp)) else: print('%s 此回合战胜%s,剩余 %s 点 hp,%s 剩余%s 点 HP'%(person.name,self.name,person.hp,self.name,self.hp)) per = Person('雷诺',100,23,'男') dog = Dog('异虫',200,12,'未知',) while 1: dog.bite(per) if per.hp < 0 or dog.hp < 0: break
流程
定义类
init 方法
self 是什么 self拥有属性都属于对象
类中可以定义静态属性
类中可以定义方法,方法都有一个必须传的参数 self
实例化
实例、对象
对象查看属性
对象调用方法
小结:
定义类
class
函数 : 方法 动态属性 # 类中可以定义方法,方法都有一个必须传的参数 self
变量 : 类属性 静态属性 # 类中可以定义静态属性
__init__ 方法 初始化方法
python 帮我们创建了一个对象 self
每当我们调用类的时候就会自动触发这个方法。默认传 self
在 init 方法里面可以对 self 进行赋值
self 是什么 self 拥有属性都属于对象
在类的内部,self 就是一个对象
alex = Person()
alex.walk == Person.walk(alex)
实例化
对象 = 类(参数是 init 方法的)
实例、对象 完全没有区别
对象查看属性
对象.属性名
对象调用方法
对象.方法名(参数) #类名.方法名(对象名,参数)