目录
一、更改类对象内的属性
一旦创建了"类"的实例和对象,就可以在主代码中轻松地设置对象内的属性,比如昨天的员工目录的代码。
如果类能够在为属性赋值之前对值进行检查,就会更实用, 这样,类就可以确保它发送的都是有效数据,这就可使类及实例 更加准确, 可靠。
下面就以一个Myclass 的类 的一个示例,它只有一个属性——数值变量 "num"。通过"__init__" 方法,我们创建一个"num" 属性,在创建实例时,向其传递参数,然后分别用 "@property" 、"@num.setter"创建在著代码获取和设置"num" 值时激活的方法。
#2取值方法,赋值方法,逻辑
class Myclass:
def __init__(self,num_passed):
self.num = num_passed#设置num 属性并设置其值
@property #每当程序获取“num”的值时调用的方法
def num(self):
print("Getting number...")
return self.__num
@num.setter #每当程序设置num值时调用的方法
def num(self,num_passed):
print("Setting number...")
if num_passed > 1000:
print("Rounding to 1000")
self.__num = 1000 #私有变量,在类内部使用
else:
self.__num = num_passed
x = Myclass(123)
print(x.num)
x.num = 9000
print(x.num)
前三行代码,它为每个类中实例化的对象提供属性“num”。但是每当“num” 获取新值时(包括"__init__"),都会调用"@num.setter" 下面的方法
我们可以在这个方法中引入某些逻辑,在必要时修改值,然后再应用到"num" ,这个程序中有一个判断条件,它的逻辑是,如果传递的值大于1000则进行舍入。还有我们设置"self.__num" (有两个下划线),而不使用"self.num"?这是因为 ,在赋值方法中设置"num" 会造成无限循环,赋值方法永远都在被调用!所以,我们才会用一个带两个下划线的私有变量,那些下划线表示这个变量只应该在类内部使用,不能从其他地方访问。
二、硬编码转换成面向对象的方式
改善程序模块性和可靠性的另一种方法是将逻辑移除主代码,然后放入类当中。
下面就先看看这个弹球程序,
如何将这段代码更面向对象,在类内部完成控制小球的工作?
2.1、硬编码弹球游戏
import sys,pygame
pygame.init()
screen = pygame.display.set_mode((640,480))
ball = pygame.image.load("ball.png")
#球的初始位置,屏幕的左上角为(0,0)然后往右是x轴,往下是y轴
ball_x = 10
ball_y = 10
#每次循环球位置的增加量
ball_x_speed =7
ball_y_speed =7
while 1:
#检查操作系统事件中,如果窗口关闭则退出
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
#更新球的x,y坐标
ball_x += ball_x_speed
ball_y += ball_y_speed
#如果弹球碰到右侧,将速度设置为负值
if ball_x>440: ball_x_speed =-7
if ball_y>300: ball_y_speed =-7
#同理撞到左侧会反向
if ball_x<0: ball_x_speed = 7
if ball_y<0: ball_y_speed = 7
#RGB填充颜色
screen.fill((90,230,90))
#指定x,y的坐标绘制球
screen.blit(ball,(ball_x,ball_y))
#将球的碰撞状态展现到屏幕
pygame.display.flip()
pygame.time.wait(10)
PS:就是一个弹球游戏,图片我没有处理好,所以看起来有点奇怪
2.2、以小球为对象完成弹球游戏
然后我们将这段代码改一改
import sys,pygame
class Ball:
def __init__(self,x,y):
self.ball_x = x
self.ball_y = y
self.ball_x_speed = 7
self.ball_y_speed = 7
self.ball_pic = pygame.image.load("ball.png")
#更新位置和速度
def update(self):
self.ball_x +=self.ball_x_speed
self.ball_y +=self.ball_y_speed
if self.ball_x> 320:self.ball_x_speed = -7
if self.ball_y> 180:self.ball_y_speed = -7
if self.ball_x<-150: self.ball_x_speed = 7
if self.ball_y<-120: self.ball_y_speed = 7
def render(self):
screen.blit(self.ball_pic,(self.ball_x,self.ball_y))
pygame.init()
screen = pygame.display.set_mode((640,480))
ball1 = Ball(240,87)
ball2 = Ball(20,25)
ball3 = Ball(180,254)
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
screen.fill((90,230,90))
ball1.update()
ball1.render()
ball2.update()
ball2.render()
ball3.update()
ball3.render()
pygame.display.flip()
pygame.time.wait(10)
很容易就变成了三个球
现在小球是对象,不再是硬编码到主代码中的,这个程序中,我们创建了3个小球,并显示其动画,我们在这个改进的程序中就是这么做的!!!
2.2.1、三个方法的讲解
"Ball" 类中有三个方法,"__init__" 用于设置起始位置,通过主代码中提过的参数设定。在这个方法中,我们还设置了球的初始速度和用于显示它的图像的 "ball.png"(图片是网上找的,我用PS处理了下,才会有现在的这个效果)。所以,每创建一个"Ball" 的一个实例时,都需要设置这些数据
在游戏中,每次循环调用球的第二个方法 "update"。这个方法相对应的更改球的位置和速度,因为这项工作是在类的内部而不是主代码完成的,所以它逐个处理方法执行。我们创建的每个小球都有自己对应的属性和方法,因此所有小球都是相互独立工作的。
最后用 "render" 方法显示小球;可以将其放在主代码中,但是如果我们想在以后增加更多特效或者更改渲染过程,放在类中会更好
2.3、小总结
在第二段更改后的程序中,我给弹球游戏增加了面向对象的特性,这意味着我们可以使用这些类创建更多的小球对象