面向过程
1.楔子
def person(name,age,sex,job): data = { 'name':name, 'age':age, 'sex':sex, 'job':job } return data def dog(name,dog_type): data = { 'name':name, 'type':dog_type } return data
上面两个方法相当于造了两个模子,游戏里的每个人和每条狗都拥有相同里的属性。游戏开始,你根据一个人或一只狗传入的具体信息来塑造一个具体的人或者狗,怎么生成呢?
d1 = dog("李磊","京巴") p1 = person("严帅",36,"F","运维") p2 = person("egon",27,"F","Teacher")
两个角色对象生成了,狗和人还有不同的功能呀,狗会咬人,人会打狗,对不对? 怎么实现呢,。。想到了, 可以每个功能再写一个函数,想执行哪个功能,直接 调用 就可以了,对不?
def bark(d): print("dog %s:wang.wang..wang..."%d['name']) def walk(p): print("person %s is walking..." %p['name'])<br><br>
面的功能实现的简直是完美!
但是仔细玩耍一会,你就不小心干了下面
p1 = person("严帅",36,"F","运维") bark(p1) #把人的对象传给了狗的方法
事实 上,从你写的代码上来看,这并没出错。很显然,人是不能调用狗的功能的,但在你的程序例没有做限制,如何在代码级别实现这个限制呢?
def person(name,age,sex,job): def walk(p): print("person %s is walking..." % p['name']) data = { 'name':name, 'age':age, 'sex':sex, 'job':job, 'walk':walk } return data def dog(name,dog_type): def bark(d): print("dog %s:wang.wang..wang..."%d['name']) data = { 'name':name, 'type':dog_type, 'bark':bark } return data d1 = dog("李磊","京巴") p1 = person("严帅",36,"F","运维") p2 = person("egon",27,"F","Teacher")
这样就实现了限制人只能用人自己的功能啦
刚才你只是阻止了两个完全 不同的角色 之前的功能混用, 但有没有可能 ,同一个种角色,但有些属性是不同的呢? 比如 ,大家都打过cs吧,cs里有警察和恐怖份子,但因为都 是人, 所以你写一个角色叫 person(), 警察和恐怖份子都 可以 互相射击,但警察不可以杀人质,恐怖分子可以,这怎么实现呢? 你想了说想,说,简单,只需要在杀人质的功能里加个判断,如果是警察,就不让杀不就ok了么。 没错, 这虽然 解决了杀人质的问题,但其实你会发现,警察和恐怖分子的区别还有很多,同时又有很多共性,如果 在每个区别处都 单独做判断,那得累死。
你想了想说, 那就直接写2个角色吧, 反正 这么多区别, 我的哥, 不能写两个角色呀,因为他们还有很多共性 , 写两个不同的角色,就代表 相同的功能 也要重写了,是不是我的哥? 。。。
面向过程 VS 面向对象
面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。
优点是:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。
缺点是:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。
应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等
面向对象的程序设计的
优点是:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现,一刀砍死3个人,这个游戏就失去平衡。
了解一些名词:类、对象、实例、实例化
类:具有相同特征的一类事物(人、狗、老虎)
对象/实例:具体的某一个事物(隔壁阿花、楼下旺财)
实例化:类——>对象的过程(这在生活中表现的不明显,我们在后面再慢慢解释)
类的相关知识
def functionName(args): '函数文档字符串' 函数体
''' class 类名: '类的文档字符串' 类体 ''' #我们创建一个类 class Data: pass
class Person: #定义一个人类 role = 'person' #人的角色属性都是人 def walk(self): #人都可以走路,也就是有一个走路方法,也叫动态属性 print("person is walking...")
类有两种作用:属性引用和实例化
属性引用(类名.属性)
class Person: #定义一个人类 role = 'person' #人的角色属性都是人 def walk(self): #人都可以走路,也就是有一个走路方法 print("person is walking...") print(Person.role) #查看人的role属性 print(Person.walk) #引用人的走路方法,注意,这里不是在调用
实例化:类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特征
class Person: #定义一个人类 role = 'person' #人的角色属性都是人 def __init__(self,name): self.name = name # 每一个角色都有自己的昵称; def walk(self): #人都可以走路,也就是有一个走路方法 print("person is walking...") print(Person.role) #查看人的role属性 print(Person.walk) #引用人的走路方法,注意,这里不是在调用
实例化:类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特征
class Person: #定义一个人类 role = 'person' #人的角色属性都是人 def __init__(self,name): self.name = name # 每一个角色都有自己的昵称; def walk(self): #人都可以走路,也就是有一个走路方法 print("person is walking...") print(Person.role) #查看人的role属性 print(Person.walk) #引用人的走路方法,注意,这里不是在调用
实例化的过程就是类——>对象的过程
原本我们只有一个Person类,在这个过程中,产生了一个egg对象,有自己具体的名字、攻击力和生命值。
语法:对象名 = 类名(参数)
egg = Person('egon') #类名()就等于在执行Person.__init__() #执行完__init__()就会返回一个对象。这个对象类似一个字典,存着属于这个人本身的一些属性和方法。 #你可以偷偷的理解:egg = {'name':'egon','walk':walk}
查看属性&调用方法
print(egg.name) #查看属性直接 对象名.属性名 print(egg.walk()) #调用方法,对象名.方法名()
关于self
self:在实例化时自动将对象/实例本身传给__init__的第一个参数,你也可以给他起个别的名字,但是正常人都不会这么做。
因为你瞎改别人就不认识
对象的相关知识
回到咱们的人狗大战:现在我们需要对我们的类做出一点点改变
人类除了可以走路之外,还应该具备一些攻击技能。
class Person: # 定义一个人类 role = 'person' # 人的角色属性都是人 def __init__(self, name, aggressivity, life_value): self.name = name # 每一个角色都有自己的昵称; self.aggressivity = aggressivity # 每一个角色都有自己的攻击力; self.life_value = life_value # 每一个角色都有自己的生命值; def attack(self,dog): # 人可以攻击狗,这里的狗也是一个对象。 # 人攻击狗,那么狗的生命值就会根据人的攻击力而下降 dog.life_value -= self.aggressivit
对象是关于类而实际存在的一个例子,即实例
对象/实例只有一种作用:属性引用
egg = Person('egon',10,1000) print(egg.name) print(egg.aggressivity) print(egg.life_value)
面向对象小结——定义及调用的固定模式
class 类名: def __init__(self,参数1,参数2): self.对象的属性1 = 参数1 self.对象的属性2 = 参数2 def 方法名(self):pass def 方法名2(self):pass 对象名 = 类名(1,2) #对象就是实例,代表一个具体的东西 #类名() : 类名+括号就是实例化一个类,相当于调用了__init__方法 #括号里传参数,参数不需要传self,其他与init中的形参一一对应 #结果返回一个对象 对象名.对象的属性1 #查看对象的属性,直接用 对象名.属性名 即可 对象名.方法名() #调用类中的方法,直接用 对象名.方法名() 即可