你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战>的游戏,你就思考呀,人狗作战,那至少需要2个角色,一个是人, 一个是狗,且人和狗都有不同的属性和技能,比如人拿棍打狗, 狗可以咬人,怎么描述这种不同的角色和他们的功能呢?
def Dog(name,s_type):
data = {
'name':name,
's_type':s_type
}
return data
def Person(name,age,sex):
data = {
'name':name,
'age':age,
'sex':sex
}
return data
两个角色对象生成了,狗和人还有不同的功能呀,狗会咬人,人会打狗. 怎么实现呢,。。想到了, 可以每个功能再写一个函数,想执行哪个功能,直接调用 就可以了,对不?
def Dog(name,s_type):
def hitPerson(d):
print('dog %s is hitting Person'%data['name'])
data = {
'name':name,
's_type':s_type,
'hitPerson':hitPerson,
}
return data
def Person(name,age,sex):
def hitDog(p):
print('person %s is hitting dog'%data['name'])
def walk(p):
print('person %s is walking '%data['name'])
data = {
'name':name,
'age':age,
'sex':sex,
'hitDog':hitDog,
'walk':walk
}
return data
上面两个函数相当于造了两个模子。游戏开始,如何塑造一个具体的人或者狗的角色呢?
d1 = Dog('doudou','金毛')
d2 = Dog('xixi','哈士奇')
p1 = Person('zhangsan',20,'F')
d1['hitPerson'](p1)
p1['hitDog'](d1)
面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的思想就好比是精心设计好一条流水线,考虑周全什么时候处理什么东西。
优点是:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。
缺点是:一套流水线就是用来解决一个问题,代码牵一发而动全身。
应用场景:
面向对象OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,并且一个对象包含数据和操作数据的方法。
形象化场景设计:
面向对象的优点:面向对象编程可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使他人更加容易理解你的代码逻辑,从而使团队开发变得更从容。
应用场景:需求经常变化的软件,如互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方。
类,英文名字Class,有“类别”,“分类”,“聚类”的意思。
必须牢记类是抽象的模板,用来描述具有相同属性和方法的对象的集合,比如Animal类。
而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。
Python使用class关键字来定义类,其基本结构如下:
class ClassName():
pass
下面是一个学生类:
class Student():
address = 'Beijing"
def __init__(self,name,age):
self.name = name
self.age = age
def read(self):
pass
def learn(self)
pass
对象的创建
可以通过调用类的实例化方法(有的语言中也叫初始化方法或构造函数)来创建一个类的实例(对象)。
Python提供了一个def __init__(self):
的实例化机制。任何一个类中,名字为__init__
的方法就是类的实例化方法,具有__init__
方法的类在实例化的时候,会自动调用该方法,并传递对应的参数。
zhangsan = Student('zhangsan',20)
实例变量
实例变量指的是实例(对象)本身拥有的变量。Student类中__init__
方法里的变量就是实例变量。
通过实例名加圆点的方式调用实例变量。
s1 = Student('zhangsan',20)
s1.name
类变量
定义在类中,构造方法之外的变量,称作类变量。类变量是所有实例公有的变量,每一个实例都可以访问类变量。
类变量可以通过类名或者实例名加圆点的方式访问类变量,比如:
s1 = Student('zhangsan',20)
s2 = Student('lisi',30)
print(Student.address) #通过类名访问类属性
print(s1.address,s2.address)#对象访问类属性,核实下类属性是否可以被对象共享
思考:如何修改类变量中存储的数据?
#通过类名修改
class Student():
address = 'Beijing' #类属性
def __init__(self,name,age):
self.name = name #实例属性
self.age = age #实例属性
def read(self):
pass
def learn(self):
pass
s1 = Student('zhangsan',20)
s2 = Student('lisi',30)
#通过类名访问类属性对齐进行修改,然后通过对象名访问类属性查看修改后的效果
print('修改前的类属性',Student.address)
Student.address = 'shanghai' #通过类名修改类属性
print('修改后的类属性',Student.address)
#通过实例名修改
class Student():
address = 'Beijing' #类属性
def __init__(self,name,age):
self.name = name #实例属性
self.age = age #实例属性
def read(self):
pass
def learn(self):
pass
s1 = Student('zhangsan',20)
s2 = Student('lisi',30)
#通过类名访问类属性对齐进行修改,然后通过对象名访问类属性查看修改后的效果
print('修改前的类属性',Student.address)
s1.address = "shanghai" #通过对象名访问类属性对其进行修改
print('修改后的类属性',s2.address)
因此一定要注意:
记住:通过对象名打点的方式只可以访问类属性,不可以修改.
如果直接通过对象名打点的方式修改类属性是不可以的,该种方式并不是对类属性进行修改,而是给该对象新增一个和类属性同名的实例变量.
Python的类中包含实例方法、静态方法和类方法三种方法。区别在于传入的参数和调用方式不同。
在类的内部,使用def
关键字来定义一个方法。
类的实例方法由实例调用,至少包含一个self参数,且为第一个参数。执行实例方法时,会自动将调用该方法的实例赋值给self。
self
代表的是类的实例,而非类本身。self
不是关键字,而是Python约定成俗的命名,你完全可以取别的名字,但不建议这么做。
class Student():
address = 'Beijing' #类属性
def __init__(self,name,age):
self.name = name #实例属性
self.age = age #实例属性
def read(self):
print(self) #self就是read方法的调用者对应的对象
print('student can read!')
def learn(self):
pass
s1 = Student('zhangsan',20)
s1.read() #不需要给self主动传参
print(s1)
对象之间的交互:可以将一个对象作为另一个对象方法的参数进行传递。
class Dog():
#构造方法的作用:对象的初始化(给创建好的对象的属性进行赋值)
def __init__(self,name,blood,agg_value):
self.name = name
self.blood = blood
self.agg_value = agg_value
def hitPerson(self,p): # p就是攻击的某个人物对象
p.blood -= self.agg_value
def showBlood(self):
return self.blood
class Persion():
def __init__(self,name,blood,agg_value):
self.name = name
self.blood = blood
self.agg_value = agg_value
def hitDog(self,d): # 被攻击者对象
d.blood -= self.agg_value
def showBlood(self):
return self.blood
d1 = Dog('doudou',100,20)
d2 = Dog('xixi',100,20)
p1 = Persion('zhangsan',100,30)
p2 = Persion('wangwu',100,30)
#让d1去攻击p1
d1.hitPerson(p1)
d1.hitPerson(p1)
print(p1.showBlood())
静态方法由类调用,无默认参数。将实例方法参数中的self去掉,然后在方法定义上方加上@staticmethod,就成为静态方法。
静态方法属于类,和实例无关。建议只使用类名.静态方法的调用方式。(虽然也可以使用实例名.静态方法的方式调用)
@staticmethod
def staticFunc(): #静态方法
print('i am static func')
类方法由类调用,采用@classmethod装饰,至少传入一个cls(代指类本身,类似self)参数。
执行类方法时,自动将调用该方法的类赋值给cls。建议只使用类名. 类方法的调用方式。
(虽然也可以使用实例名.类方法的方式调用)
class Obj():
def instanceFunc(self): # 普通的实例方法
print('i am instance func')
@classmethod # 装饰器
def classFunc(cls): # 类方法,cls就是当前类
print('i am class func')
Obj.classFunc() # 尽量使用类名调用类方法
组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合
思路设计:一个学生会有一部手机,学生使用手机看电影。
class CellPhone():
def __init__(self,color,c_type):
self.color = color
self.c_type = c_type
def watchMovie(self,title):
print('watching %s ......'%title)
class Student():
def __init__(self,name,age):
self.name = name
self.age = age
self.cellPhone = CellPhone('red','iphone')
s1 = Student('lisi',20)
s1.cellPhone.watchMovie('霸王别姬')