我不确定标题是否给出了最好的描述。但这是我的问题。 我有一个名为'Ball'的班级。 每个球都有自己的宽度,半径和颜色。 在我循环之前添加自己的球时,我的代码工作得很好 例如。 ball1 = Ball().... ball2 = Ball() 我正在使用pygame和我想要的是每当我按下'Space'时它会添加另一个具有它自己特征的球。我有它,以便随机给出宽度,半径和颜色。 这是我的代码:
BLACK = (0,0,0)
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
fps = 30
color_list = [BLACK, BLUE, GREEN, RED]
col = None
siz = None
wit = None
posx = None
posy = None
ball = None
class Ball:
ballCount = 0
def __init__(self):
Ball.ballCount +=1
self.col = random.choice(color_list)
self.siz = random.randint(20, 80)
self.wit = random.randint(1, 3)
self.posx = random.randint(self.siz, width-self.siz)
self.posy = random.randint(self.siz, height-self.siz)
def blitball(self):
pygame.draw.circle(screen, self.col, (self.posx, self.posy),self.siz, self.wit)
def move(self):
self.posx+=1
ball2 = Ball()
ball1 = Ball()
ball3 = Ball()
while True:
amount = 0
event = pygame.event.poll()
keys = pygame.key.get_pressed()
if event.type == QUIT:
pygame.quit()
sys.exit()
if keys[K_q]:
pygame.quit()
sys.exit()
#############################################################
if keys[K_SPACE]:
eval("ball"+str(Ball.ballCount+1)) = Ball()
#############################################################
screen.fill(WHITE)
for r in range(Ball.ballCount):
amount+=1
eval("ball"+str(amount)).move()
eval("ball"+str(amount)).blitball()
pygame.time.wait(int(1000/fps))
pygame.display.update()
使用for r in range(Ball.ballCount):
因此我不必为每个球键入函数。这非常有效。如果您知道一种更简单的方式让我知道。
所以我需要补充的是:
if keys[K_SPACE]:
#add another ball, ball3, ball4,..etc.
如果这意味着更改我的部分代码,请随时告诉我,甚至自己这样做。 感谢您提前回复。 (我在HASHTAGS中有我的问题)
丹尼斯
答案 0 :(得分:3)
将您的球存放在列表中并在那里采取行动
# starting three balls
balls = [Ball(),Ball(),Ball()]
while True:
amount = 0
event = pygame.event.poll()
keys = pygame.key.get_pressed()
if event.type == QUIT:
pygame.quit()
sys.exit()
if keys[K_q]:
pygame.quit()
sys.exit()
#############################################################
if keys[K_SPACE]:
balls.append(Ball())
#############################################################
screen.fill(WHITE)
for ball_in_play in balls:
ball_in_play.move()
ball_in_play.blitball()
pygame.time.wait(int(1000/fps))
pygame.display.update()
答案 1 :(得分:2)
您几乎不想按名称创建新变量。
而且,即使在极少数情况下,您也几乎不想使用eval
或exec
。
而且,即使您确实想要使用eval
或exec
,也几乎不想将它们与默认locals
/ globals
一起使用。
但是,让我们看一下为什么你的代码不能先工作,然后再考虑如何做得更好。
eval("ball"+str(Ball.ballCount+1)) = Ball()
您正在生成类似"ball4"
的字符串,然后在其上调用eval
。毫不奇怪,评估字符串"ball4"
。然后你试图将一个新值(新构造的Ball
实例)分配给该字符串,而不是变量,显然这将不起作用。 (实际上,我猜你在尝试分配函数调用之前会得到SyntaxError
,甚至在评估任何东西之前。)
要解决这个问题,你必须将整个事情放在eval
:
eval("ball"+str(Ball.ballCount+1) + " = Ball()")
但这不起作用,因为eval
仅适用于表达式,而不适用于语句。对于陈述,您需要exec
:
exec("ball"+str(Ball.ballCount+1) + " = Ball()")
这将消除你的错误。
但是让我们看一下创建ball4
变量的正确方法:
locals()["ball" + str(Ball.ballCount+1)] = Ball()
更简单,更容易出错。
但是,一旦你看到这一点,当你可以使用任何你想要的locals()
dict
时,为什么还要使用dict
作为my_balls["ball" + str(Ball.ballCount+1)] = Ball()
呢?
my_balls[Ball.ballCount+1] = Ball()
而且,一旦你完成了这项工作,你就不需要每个人的“球”前缀:
list
此时,您可能会发现您的密钥只是自然数字,这意味着您只是使用dict
来模拟my_balls
,所以您不妨只做{{ 1}} list
。
然后,您不再需要Ball.ballCount
- 它只是len(my_balls)
。
那么,使用eval
和exec
会有什么不好?
嗯,它的效率较低,它使您的代码更难调试(并在交互式终端中进行试验),并且会打开巨大的安全漏洞(想象您向用户询问了下一个球号,他给了你返回“3; os.system('rm -rf /'); _”然后你尝试exec("Ball" + user_input_string + " = Ball()")
)。
但与所有这些相比,它使您的代码更难以阅读。比较:
eval("ball"+str(amount)).move()
balls[amount].move()