[Tutor] A more Pythonic way to do this

Adam Bark adam.jtm30 at gmail.com
Fri Jul 1 03:26:24 CEST 2005


Good, good. I probably wouldn't have been able to help you if it was 
something so simple but that screws up your program and makes it hard to 
find out just what is going on. Anyway good look with anymore tidying on 
that you might be doing. Any chance of a copy?

Adam

On 7/1/05, D. Hartley <denise.hartley at gmail.com> wrote:
> 
> ..... it was a paren.
> 
> I was so worried that I just wasn't figuring it all out, that I had
> tried to write elegant code and wasnt understanding the fundamentals,
> and the only reason it didnt work was because I left out a paren.
> 
> I actually laughed until I cried.
> 
> Thanks for that. And yes, it works now ;) it's lovely.
> 
> ~Denise
> 
> On 6/30/05, Adam Bark <adam.jtm30 at gmail.com> wrote:
> > Here's the problem -->
> > enemyship_sprites.add(Enemy((cols*60)+20, (rows*40)+30),
> > level)
> >
> > 1,2 1 2
> > 1 0
> > you've put a braket after +30 which ends the Enemy call. The numbering 
> is +1
> > for opening braket -1 for closing so 0 is the end of the Enemy call if 
> you
> > understand this.
> >
> >
> > On 6/30/05, D. Hartley <denise.hartley at gmail.com> wrote:
> > >
> > > Hey guys!
> > >
> > > I have a 'quest,' and at first glance this email looks long, but the
> > > problem is probably not as complex as the length implies. Please bear
> > > with me, if I could get some advice on this particular problem, it
> > > would go along way toward helping me be a better Python programmer.
> > >
> > > Some of you might remember, a few months ago, I was working on a space
> > > invaders game for a birthday present. One of the functions I really
> > > wanted to add to the game was to change the enemy "ships" at each new
> > > level. Because of my deadline and my newness to Python, I did this in
> > > an extremely ugly way. To give you an idea:
> > >
> > > the original main loop called:
> > > enemyship_sprites = createEnemies(screen, enemy_speed)
> > >
> > > createEnemies looks like this:
> > >
> > > def createEnemies(screen, speed):
> > > enemyship_sprites = EnemySprites(speed)
> > > for rows in xrange(5):
> > > for cols in xrange(8):
> > > enemyship_sprites.add(Enemy((cols*60)+20,
> > (rows*40)+30), level)
> > > enemyship_sprites.draw(screen)
> > > return enemyship_sprites
> > >
> > > It creates an instance of EnemySprites (my holder class) which
> > > contains code for when the ships hit bottom, when to update them, etc.
> > > It also calls "Enemy()", which looks like this:
> > >
> > > class Enemy(pygame.sprite.Sprite):
> > > def __init__(self, startx, starty):
> > > pygame.sprite.Sprite.__init__(self)
> > > if level == 1:
> > > self.image, self.rect = load_image('salad_ship.bmp', -1)
> > > self.rect.centerx = startx
> > > self.rect.centery = starty
> > > def update(self, direction, go_down):
> > > jump = 40 # how much the enemies move to the right/left on
> > > each jump
> > > if go_down:
> > > # if a ship is moving down on this round,
> > > # it doesn't move on the x-axys
> > > self.rect.move_ip((0, 5))
> > > else:
> > > # move a ship in the x-axys.
> > > # if direction=1, it moves to the right; -1 to the left
> > > self.rect.move_ip((jump * direction, 0))
> > > # maybe it's time for a shot? :)
> > > # the chances are 1/30
> > > dice = random.randint (0,30)
> > > global enemy_shot_sprites
> > > if dice == 1:
> > > shot = EnemyShot(self.rect.midtop)
> > > enemy_shot_sprites.add(shot)
> > >
> > >
> > > Now, get ready for one of the uglier things you've probably seen 
> lately
> > (!!):
> > >
> > > Since I can only access the variable "level" from within the main
> > > loop, for some reason I thought I couldnt use it in my class
> > > definitions (which of course come before and are outside of the
> > > mainloop). So within the main loop, I did:
> > >
> > > if level == 1:
> > > enemyship_sprites = createEnemies1(screen,
> > enemy_speed)
> > > elif level == 2:
> > > enemyship_sprites = createEnemies2(screen,
> > enemy_speed)
> > > elif level == 3:
> > > enemyship_sprites = createEnemies3(screen,
> > enemy_speed)
> > > elif level == 4:
> > > enemyship_sprites = createEnemies4(screen,
> > enemy_speed)
> > > elif level == 5:
> > > enemyship_sprites = createEnemies5(screen,
> > enemy_speed)
> > > elif level == 6:
> > > enemyship_sprites = createEnemies6(screen,
> > enemy_speed)
> > > elif level == 7:
> > > enemyship_sprites = createEnemies7(screen,
> > enemy_speed)
> > > elif level == 8:
> > > enemyship_sprites = createEnemies8(screen,
> > enemy_speed)
> > > else:
> > > enemyship_sprites = createEnemies9(screen,
> > enemy_speed)
> > >
> > > And yes, I created 9 different createEnemies, all pretty much carbon
> > > copies of each other except that they called Enemy1, Enemy2, Enemy3,
> > > etc. And then (you guessed it), I created 9 different Enemy
> > > functions, too, so that each one could have its own (different)
> > > bitmap.
> > >
> > > Now... this is just ridiculous.
> > >
> > > To my credit, I did actually know that at the time. But the day before
> > > the birthday, I figured if I could make it work somehow, I would, and
> > > I'd make it prettier later. Now just happens to be that later ;)
> > >
> > > So now that I've got a little more Python experience under my belt
> > > (not much, but a little), it occurred to me that when I call
> > > createEnemies in the mainloop, I could pass in an argument 'level'.
> > >
> > > mainloop now starting off with:
> > > enemyship_sprites = createEnemies(screen, enemy_speed, level)
> > >
> > > level is one of my main loop variables, so it'll know what i'm talking
> > > about and can take that variable and pass it in when it calls
> > > createEnemies. (Btw, please forgive me if I mix up terms like argument
> > > and variable or use them in the wrong places, I'm still getting used
> > > to them!) In any case, then I changed my createEnemies to look like
> > > this:
> > >
> > > def createEnemies(screen, speed, level):
> > > enemyship_sprites = EnemySprites(speed)
> > > for rows in xrange(5):
> > > for cols in xrange(8):
> > > enemyship_sprites.add(Enemy((cols*60)+20,
> > (rows*40)+30), level)
> > > enemyship_sprites.draw(screen)
> > > return enemyship_sprites
> > >
> > > Since the part that changes each level actually matters when the Enemy
> > > function gets called (because that's where the bmps are loaded), I
> > > made Enemy need 'level':
> > >
> > > class Enemy(pygame.sprite.Sprite):
> > > def __init__(self, startx, starty, level):
> > > pygame.sprite.Sprite.__init__(self)
> > > if level == 1:
> > > self.image, self.rect = load_image('salad_ship.bmp', -1)
> > > elif level == 2:
> > > (.................etc)
> > > self.rect.centerx = startx
> > > self.rect.centery = starty
> > > (...............etc)
> > >
> > >
> > > Now I know this email is getting hard to read ;)
> > >
> > > At this point I was thinking I'd have one createEnemies, called in the
> > > mainloop, which would take the level and, when it called Enemy to
> > > create the ships, use that level argument to determine which bmp to
> > > use for the ship itself. One createEnemies(), one Enemy(), there you
> > > go.
> > >
> > > But now it's giving me an error when createEnemies is called, for the
> > > enemyship_sprites.add(Enemy((cols*60)+20, (rows*40)+30),
> > level) line,
> > > saying __init__() (and this would be Enemy's init, correct?) takes
> > > exactly 4 arguments (3 given): and Enemy's init, as you can see,
> > > takes (self, startx, starty, level). But the first argument is just
> > > 'self'! I don't have to pass that in.... I never *did*, anyway, in
> > > all my Enemy1, Enemy2, Enemy3 code...?
> > >
> > > I can send the full code for anybody who thinks that would be
> > > clearer to look at (ha ha) - I was going to attach it here but it
> > > would make the message too big for the list. I know that going
> > > through such a messy
> > > problem like this is a pain, and questions like this don't always get
> > > a lot of responses on the list. My code worked, it was just messy,
> > > and so I suppose I could just leave it alone. But I want to clean it
> > > up: I want to make it more Pythonic, more organized, more efficient,
> > > and would really love any advice anyone could offer.
> > >
> > > Heck, for all I know, I could just be needing to add a "self.___"
> > > somewhere, heaven knows that has tripped me up before!
> > >
> > > Would love to hear from you guys, and thanks again,
> > > Denise
> > > _______________________________________________
> > > Tutor maillist - Tutor at python.org
> > > http://mail.python.org/mailman/listinfo/tutor
> > >
> >
> >
> _______________________________________________
> Tutor maillist - Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.python.org/pipermail/tutor/attachments/20050701/03723b31/attachment-0001.htm


More information about the Tutor mailing list