1、场景:
玩过游戏。主人公,进入了一个场景,有10个小怪物是一样的。有攻击力,血(100格)。如果小怪物有多个数值需要管理,小怪物的血量、小怪物出现在屏幕的地点。
可以使用字典来进行记录:
{"blood":100,"location":"10,10"}
[[100,(10,10)]]
10 个小怪物。记住10个小怪物所有的变量在哪里,怎么操作?
写一些函数,来操作这些数据。
函数你实现的时候,你觉得需要实现哪些功能?
10个方法:所有操作的数据的方法
add_blood():
blood+=1
minus_blood():
blood-=1
move():
x-=10
y-=10
类的好处:
1) 把数据封装到实例里面,用同一的规则来进行存取,保证数据的安全和一致性
2)基于类,方便进行扩展 (设计模式)
3)类相当于模板,可以通过构造函数做初始化,快速生成实例
"""小怪物的类,类定义"""
def __init__(self,blood,location_x,location_y): #构造函数,用来传参,可以无参
self.blood = blood
self.location_x = location_x
self.lcoation_y = location_y
def add_blood(self,num): #实例方法:方法中有self参数
if self.blood<=100:
self.blood+=num
if self.blood>100:
self.blood = 100
def minus_blood(self,num): #实例方法:方法中有self参数
if self.blood>=0:
self.blood-=num
if self.blood<0:
self.blood = 0
def tell_blood(self): #实例方法:方法中有self参数
return self.blood
s1= soldier(100,10,10) #实例化,传参
s2= soldier(90,10,20) #实例化,传参
s3= soldier(80,10,30) #实例化,传参
print(s1.tell_blood()) #调tell_blood函数,输出每个小怪物的血量
print(s2.tell_blood())
print(s3.tell_blood())
"""小怪物的类,类定义"""
class soldier():
def __init__(self,blood,location_x,location_y): #构造函数,用来传参,可以无参
self.blood=blood
self.location_x=location_x
self.location_y=location_y
def add_blood(self,num): #实例方法:方法中有self参数
if self.blood<=100:
self.blood+=num
if self.blood>100:
self.blood=100
return self.blood
def minus_blood(self,num): #实例方法:方法中有self参数
if self.blood>=0:
self.blood-=num
if self.blood<0:
self.blood=0
return self.blood
def tell_blood(self): #实例方法;方法中有self参数
return self.blood
s1=soldier(89,10,10) #实例化,用模板做出来的东西,传参
s2=soldier(67,10,20) #实例化,用模板做出来的东西,传参
s3=soldier(23,10,30) #实例化,用模板做出来的东西,传参
print(s1.add_blood(70)) #调用add_blood函数,给小怪物1加血
print(s2.minus_blood(80)) #调用minus_blood函数,给小怪2物减血
print(s3.add_blood(80)) #调用add_blood函数,黑小怪物3加血
运行结果:
E:\>python a.py
100
0
100
2、类:(相关数据存在一起,并且有一组操作相关数据的方法)
2)方法(类里面写的函数叫做方法。)
类比说明:
生产杯子,杯子的模具(类),可以设定不同的参数来生产杯子。
设定好不同的参数(通过构造函数传参),生产出具体的杯子(实例化)。
类:soldier
实例化:传入不同的参数(调用构造函数)
s1
s2
s3
3、批量生成实例化对象
class circle(object): #object可写可不写
def __init__(self,radius):
self.radius = radius #radius这个变量在构造函数里,是一个局部变量,走出构造函数,radius这个变量是不能使用的。如果要使用该变量值,需要存在一个带self.的变量中,才能在其他的类方法中使用该值
def get_area(self):
return math.pi*self.radius*self.radius #self.XXX称作实例变量
def get_perimeter(self):
return 2*math.pi*self.radius
for i in range(1,6):
a= circle(i)
print(a.get_area())
print(a.get_perimeter())
#self.xxxx实例变量
#在类里面定义的函数叫做方法
def add():#函数
return a+b
1. 如果用列表存储数据:
def set(a,index,new_value):
if new_value>=0: #当输入的值>=0时,新值会替代原始数据
a[index] = new_value
set(a,0,100) #新输入的值为100大于0,替换a[0]的值
print(a)
set(a,0,-50) #新输入的值为-50,小于0.不会替换a[0]的值
print(a)
2)但是无法限制别人修改值
a[0]=-50print(a)
2. 用类来实现限制修改输入负数
def __init__(self,a):
self.__value = a #将输入的列表值赋值给实例变量
def set(self,index,value):
if value<0: #当输入的值为负数时,什么都不做
return
self.__value[index] = value #当输入的不为负数时,替换a中的数据;两个下划线是私有变量,除了类中的实例方法可以访问,外部不可以直接访问和修改
def get(self):
return self.__value #读取列表中的值
p= positive_num_list([1,2,3,4]) #a=[1,2,3,4]
p.__value[0]=-100 #类保护了数据被修改
运行结果:
AttributeError: 'positive_num_list' object has no attribute '__value'
print(p.get()) #结果:[1, 2, 3, 4]
p.set(1,50) #试图替换a[1]的值为50
print(p.get()) #读取替换后的值,结果:[1, 50, 3, 4]
print(set([1,1,2,2]))
结果:{1, 2} #set集合去重
class positive_num_list(object):
def __init__(self,a):
self.value=a #实例变量没有双下划线
def set(self,index,value):
if value<0:
return
self._value[index]=value
def get(self):
return self._value
p=positive_num_list([1,2,3,4])
p.value[0]=-8 #尝试修改数值
print(p.get())
运行结果:
E:\>python a.py
[-8, 2, 3, 4] #数据依然被是修改成功,说明私有变量的重要性
3.用类来限制修改半径:
class circle(object):
def __init__(self,radius):
if radius<=0: #当输入值是<=0的数时,将输入值重新赋值为1
self.radius = 1
else:
def modify_radius(self,radius): #可以定义一个方法,限制输入值是负数
if radius<0:
self.radius = abs(radius)
elif radius==0:
self.radius = 1
def get_area(self):
return math.pi*self.radius*self.radius
def get_perimeter(self):
return 2*math.pi*self.radius
c=circle(-1) #走构造函数的程序
print(c.get_area())
c.modify_radius(-2) #调用modify_radius方法
print(c.get_area())
def __init__(self,value): #构造方法,初始化的
self.value = value #value局部变量,self.value叫做实例变量
p =P(10)
print(p.value)
p.value=-10
print(p.value)
def __init__(self,value): #构造方法,初始化的
self.__value = value #value局部变量,self.value叫做实例变量
p =P(10)
print(p.__value) #私有变量
def __init__(self,value): #构造方法,初始化的
self.__value = value #value局部变量,self.value叫做实例变量
def get(self): #实例方法
return "***:"+str(self.__value)
def set(self,value): #实例方法
if isinstance(value,(int,float)):
self.__value = value
return None
p =P(10)
print(p.get()) #私有变量
p.set("a")
print(p.get()) #私有变量
p.set(-5)
print(p.get()) #私有变量
def __init__(self,value): #构造方法,初始化的
self.__value = value #value局部变量,self.value叫做实例变量
def get(self): #实例方法
return "***:"+str(self.__value)
def set(self,value): #实例方法
if isinstance(value,(int,float)):
self.__value = value
return None
p1 =P(1)
p2 =P(2)
p3 =P(3)
内存中的位置:A
P:类变量
类定义的方法
类中所有定义的方法,类变量,只有一份
实例在内存中:有0个,1个或多个
内存中的位置:b
p1的实例:self.__value=1
内存中的位置:c
p2的实例:self.__value=2
内存中的位置:d
p3的实例:self.__value=3
p1.get()--->p1的实例调用get的方法:调用的时候,会把内存位置b发送给类定义的方法P.get
self:是一个方法的参数,该参数传的值是内存b的位置
get方法从内存b的位置找到__value值,然后执行方法中的代码。
但是定义的时候:def get(self),有self参数,调用的时候p1.get(),没有self.
实际get拿到了self的地址(该方法在内存中的位置b),找到了__value值
如果不把self的值传过去,找不到value所在的内存地址,方法执行失败
self传递的是某个实例的地址。实例地址里面的所有变量都可以在方法中进行使用。
TypeError: set() takes 2 positional arguments but 3 were given
变量前面带有self.的叫做实例变量,可以在多个方法中访问,实例变量都存在对应的实例所在的内存地址中。
如果不加self.的叫做局部变量,不能跨方法访问
class P(object):
def __init__(self,value): #构造方法,初始化的
value1=value #value1和value局部变量,不能跨方法访问
def get(self):
return value1 #在这个方法中返回value1
p1=P(1)
print(p1.get())
运行结果
E:\>python a.py
Traceback (most recent call last):
File "a.py", line 10, in <module>
print(p1.get())
File "a.py", line 7, in get
return value1
NameError: name 'value1' is not defined #value1未定义
1 可以封装数据,制定数据的存储规则,保证数据的安全
2 类相当于模板,可以通过构造函数做初始化,快速生成实例
3 基于类,可以进行扩展。(设计模式)
4 内存中存储的类变量和方法,只有一份。每个类的实例,都在内存中有一个地址(类产生的实例可以有0个、1个或多个)
5 类中定义的实例方法(方法中有self参数),可以操作每个实例中封装的变量
6 实例变量(self.开头的)可以在不同的实例方法中被访问。实例变量都存在对应的实例所在的内存地址中。
7 __变量是私有变量,除了类中的实例方法可以访问,外部不可以直接访问和修改。