面向对象编程(1)
楔子
你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战>的游戏,你就思考呀,人狗作战,那至少需要2个角色,一个是人,一个是狗,且人和狗都有不同的技能,比如人拿棍打狗, 狗可以咬人,怎么描述这种不同的角色和他们的功能呢?你搜罗了自己掌握的所有技能,写出了下面的代码来描述这两个角色
版本1:
def hero(name,sex,hp,ce,level=2,exp=2000,money=10000): hero_info = { 'name':name, 'sex':sex, 'hp':hp, # 血值 'ce':ce, # 战斗力 "level":level, # 级别 "exp":exp, # 经验 "money":money # 金币 } return hero_info def dog(name,dog_type,hp,ce): dog_info = { 'name':name, 'dog_type':dog_type, 'hp':hp, 'ce':ce, } return dog_info def bite(dog,hero): print("%s咬了%s"%(dog["name"],hero["name"])) def attack(hero,dog): print("%s攻击了%s"%(hero["name"],dog["name"])) alex=hero("alex","male",100,80) xiaohei=dog("小黑","藏獒",100,5) # 但是方法之间没有关联性,就会出现如下问题 bite(alex,xiaohei) # alex咬了小黑,这alex真牛逼,谁都敢咬
版本2:
def hero(name,sex,hp,ce,level=2,exp=2000,money=10000): hero_info = { 'name':name, 'sex':sex, 'hp':hp, # 血值 'ce':ce, # 战斗力 "level":level, # 级别 "exp":exp, # 经验 "money":money # 金币 } def attack(dog): print("%s攻击了%s"%(hero_info["name"],dog["name"])) hero_info["attack"]=attack return hero_info def dog(name,dog_type,hp,ce): dog_info = { 'name':name, 'dog_type':dog_type, 'hp':hp, 'ce':ce, } def bite(hero): print("%s咬了%s"%(dog_info["name"],hero["name"])) dog_info["bite"]=bite # 闭包 return dog_info alex=hero("alex","male",100,80) xiaohei=dog("小黑","藏獒",100,5)
面向过程 VS 面向对象
面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。
举例:把大象装进冰箱需要三步:
面向过程的程序设计
面向过程的程序设计的核心是过程(流水线式思维), 过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。
优点是:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。
缺点是:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。
应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等。
面向对象的程序设计
优点是:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。
应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方。
在python 中面向对象的程序设计并不是全部。
面向对象编程可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。
其实,上帝就是一个程序员,基于面向对象的思想创造了世界万物。
类与对象
声明类
# 函数声明 def 函数名(args): 函数体 # 声明一个类 class 类名: 类变量=值 def 实例方法(self,*args,**kwargs): pass # 示例 class Dog: legs=4 # 类变量 def __init__(self,name,type): # 类必不可少的方法,用于实例化 self.name=name self.type=type def bite(self): # 根据Dog类自定义的实例方法 print("bite...")
注意,__init__()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法
类实例化
实例化的过程就是由类创建具体对象的过程。
alex=Dog("alex","藏獒") egon=Dog("egon","京巴")
注意类与对象的内存的存储关系!
self
self代表类的实例,而非类。类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。
class Dog: legs=4 # 类变量 def __init__(self,name,type): # 类必不可少的方法,用于实例化 self.name=name self.type=type def bite(self): # 根据Dog类自定义的实例方法 print("bite...") print("self",self) alex=Dog("alex","藏獒") alex.bite() print("alex",alex)
从执行结果可以很明显的看出,self 代表的是类的实例,代表当前对象的地址。self 不是 python 关键字,我们把他换成 this 或者其他任何单词也是可以正常执行的。
类实例变量的增删改查
class Hero: def __init__(self,name,sex,hp,ce,level=2,exp=2000,money=10000): # 类必不可少的方法,用于实例化 self.name=name self.sex=sex self.hp=hp self.ce=ce self.level=level self.exp=exp self.money=money alex=Hero("alex","male",100,80) # 查看属性 print(alex.sex) print(alex.money) # 添加一个属性(实例变量) alex.age=1000 # 修改属性 alex.age=999 # 删除属性 del alex.age
注意实例对象有一个__dict__的属性,可以打印下看看是什么。
好了现在我们可以基于Python的类来实现我们的人狗大战了!
一切皆对象
其实,我们使用的所有数据都是具体类的实例对象,比如str,list等等。
面向对象的组合用法
软件重用的重要方式除了继承之外还有另外一种方式,即:组合。组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合
class Weapon: def __init__(self,name,av,color): self.name=name self.av=av self.color=color gun=Weapon("激光枪",100,"red") class Hero: def __init__(self,name,sex,hp,ce,weapon,level=2,exp=2000,money=10000): # 类必不可少的方法,用于实例化 self.name=name self.sex=sex self.hp=hp self.ce=ce self.level=level self.exp=exp self.money=money self.weapon=weapon alex=Hero("alex","male",100,80,gun) print(alex.weapon.color)