无论用什么形式来编程,我们都要明确记住以下原则:
1.写重复代码是非常不好的低级行为
2.你写的代码需要经常变更
开发正规的程序跟那种写个运行一次就扔了的小脚本一个很大不同就是,你的代码总是需要不断的更改,不是修改bug就是添加新功能等,所以为了日后方便程序的修改及扩展,你写的代码一定要遵循易读、易改的原则(专业数据叫可读性好、易扩展)。
如果你把一段同样的代码复制、粘贴到了程序的多个地方以实现在程序的各个地方调用这个功能,那日后你再对这个功能进行修改时,就需要把程序里多个地方都改一遍,这种写程序的方式是有问题的,因为如果你不小心漏掉了一个地方没改,那可能会导致整个程序的运行都 出问题。因此我们知道在开发中一定要努力避免写重复的代码,否则就相当于给自己再挖坑。
函数的出现就能帮我们轻松的解决重复代码的问题,对于需要重复调用的功能,只需要把它写成一个函数,然后在程序的各个地方直接调用这个函数名就好了,并且当需要修改这个功能时,只需改函数代码,然后整个程序就都更新了。函数编程与OOP的主要区别就是OOP可以使程序更加容易扩展和易更改。
eg:制作一个CS
非OOP方法定义:
#role 1
name = 'Hunter'
role = 'terrorist'
weapon = 'AK47'
life_value = 100
money = 10000
#rolw 2
name2 = 'Jack'
role2 = 'police'
weapon2 = 'B22'
life_value2 = 100
money2 = 10000
#role 3
name3 = 'Tom'
role3 = 'terrorist'
weapon3 = 'C33'
life_value3 = 100
money3 = 10000
#rolw 4
name4 = 'Marry'
role4 = 'police'
weapon4 = 'B51'
life_value4 = 100
money4 = 10000
4个角色虽然创建好了,但是有个问题就是,每创建一个角色,我都要单独命名,name1,name2,name3,name4…,后面的调用的时候这个变量名你还都得记着,要是再让多加几个角色,估计调用时就很容易弄混。我们只需要把上面的变量改成字典的格式。
roles = {
1:{'name':'Hunter',
'role':'terrorist',
'weapon':'AK47',
'life_value': 100,
'money': 15000,
},
2:{'name':'Jack',
'role':'police',
'weapon':'B22',
'life_value': 100,
'money': 15000,
},
3:{'name':'Tom',
'role':'terrorist',
'weapon':'C33',
'life_value': 100,
'money': 15000,
},
4:{'name':'Marry',
'role':'police',
'weapon':'B51',
'life_value': 100,
'money': 15000,
},
}
print(roles[1]) #Hunter
print(roles[2]) #Jack
定义功能:
def shot(by_who):
#开了枪后要减子弹数
pass
def got_shot(who):
#中枪后要减血
who[‘life_value’] -= 10
pass
def buy_gun(who,gun_name):
#检查钱够不够,买了枪后要扣钱
pass
...
出现的问题:
每个角色定义的属性名称是一样的,但这种命名规则是我们自己约定的,从程序上来讲,并没有进行属性合法性检测,也就是说role 1定义的代表武器的属性是weapon, role 2 ,3,4也是一样的,不过如果我在新增一个角色时不小心把weapon 写成了wepon , 这个程序本身是检测不到的。
terrorist 和police这2个角色有些功能是不同的,比如police是不能杀人质的,但是terrorist可能,随着这个游戏开发的更复杂,我们会发现这2个角色后续有更多的不同之处, 但现在的这种写法,我们是没办法 把这2个角色适用的功能区分开来的,也就是说,每个角色都可以直接调用任意功能,没有任何限制。
我们在上面定义了got_shot()后要减血,也就是说减血这个动作是应该通过被击中这个事件来引起的,我们调用get_shot(),got_shot()这个函数再调用每个角色里的life_value变量来减血。 但其实我不通过got_shot(),直接调用角色rolesrole_id 减血也可以呀,但是如果这样调用的话,那可以就是简单粗暴啦,因为减血之前其它还应该判断此角色是否穿了防弹衣等,如果穿了的话,伤害值肯定要减少,got_shot()函数里就做了这样的检测,你这里直接绕过的话,程序就乱了。 因此这里应该设计 成除了通过got_shot(),其它的方式是没有办法给角色减血的,不过在上面的程序设计里,是没有办法实现的。
现在需要给所有角色添加一个可以穿防弹衣的功能,那很显然你得在每个角色里放一个属性来存储此角色是否穿 了防弹衣,那就要更改每个角色的代码,给添加一个新属性,这样太low了,不符合代码可复用的原则。
用OOP中的“类”:
class Role(object):
def __init__(self, name, role, weapon, life_value=100, money=15000):
self.name = name
self.role = role
self.weapon = weapon
self.life_value = life_value
self.money = money
def shot(self):
print("%s is shooting..." % self.name)
def got_shot(self):
print("ah...,I got shot...")
def buy_gun(self, gun_name):
print("%s just bought %s" % (self.name, gun_name))
self.weapon = gun_name
r1 = Role('Hunter', 'police', 'AK47') #生成一个角色
r2 = Role('Jack', 'terrorist', 'B22') #生成一个角色
r1.shot()
r2.buy_gun("B46")
print(r2.weapon)
代码量少了近一半
角色和它所具有的功能可以一目了然看出来
类的语法
class Dog(object):
def sayshi(self):
print("hello,I am a dog!")
d = Dog() #实例化这个类,
d.sayshi() # 调用具体的功能
class Dog(object):
def __init__(self, name, dog_type):#构造方法,构造函数 == 初始化方法
self.name = name
self.type = dog_type
def sayhi(self):#类的方法
print("hello,I am a dog, my name is ", self.name)
def eat(self,food):
print("%s is eating %s" %(self.name,food))
d = Dog('Jack', "京巴")#实例化后产生的对象叫 实例
d.sayhi()