1

More and more I realize my code is getting filled with if/else statements. Eventually, I started to write one-liners (x = 'this' if y > 0 else 'that') and, in some cases, if a test were often true, I assumed it was from the beginning and only changed anything if it weren't. For example:

From this

def increase_score(self, side)
    if self.player.side == side:
        self.enemy.score += 1
    else:
        self.player.score += 1

I would do this

def increase_score(self, side)
    # assume player.side is side
    last_enemy_score = self.enemy.score
    self.enemy.score += 1
    # only change if player.side isn't side
    if self.player.side != side:
         self.enemy.score = last_enemy_score
         self.player.score += 1

Besides these two approaches, what are some interesting alternatives to line-by-line if/else statements?

bzrr
  • 1,490
  • 3
  • 20
  • 39

3 Answers3

4

I think you are overlooking one big logic simplicity. In both cases the player 'wins' if their player.side is different to side, otherwise the enemy 'wins'.

Why not just use this:

if self.player.side == side:
    self.enemy.score += 1
else:
    self.player.score += 1

edit: Clever options below

Since you are asking for alternatives, here are a few that would also work. Note however, that often simple predictable code is better than clever.

Casting binary to integers (only works if you want to add either 0 or 1):

self.enemy.score  += int(self.player.side == side)
self.player.score += int(self.player.side != side)

Calling from an array using a binary (only works with 2 options).

winner = [self.player,self.enemy][self.player.side == side]
winner.score += 1

Calling from a dictionary via a tuple - this would work if you added up and down or wanted some player options to always win.

 challenge = { ('left','left')   : self.enemy,
               ('left','right')  : self.player,
               ('right','right') : self.enemy,
               ('right','left')  : self.player }

 winner = challenge[(self.player.side,side)]
 # OR safely assuming the enemy is the defualt winner
 winner = challenge.get((self.player.side,side), self.enemy) 
  • Still, what I want to know is about other ways to implement if/else functionality. – bzrr Sep 17 '13 at 23:27
  • @Jovito Its hard to answer without some troublesome code. In your case, `if/then/else` works and is consistent with other code. –  Sep 17 '13 at 23:28
  • @Jovito I stand by the simple option, however I've given you a few more 'clever' solutions. If this helps, feel free to accept the answer :) –  Sep 17 '13 at 23:38
3

Use a dict to get rid of low-level if statements.

score = dict(left=0, right=0)
players = dict(left='Jack', right='Jill')

def increase_score(self, side):
    score[side] += 1

It is very easy to query the score for any player, and find their current side, and of course incrementing the score is now trivial.

Thinking about this a bit more, how would we handle something like a round-robin tournament, where there are many competitors but fewer games happening at any one time? Here I would rather key the score dict by player name, and then do a lookup inside the function:

score = {'Jack':0, 'Jill':0, 'Jane':0}
current_players = dict(left='Jane', right='Jill')

def increase_score(self, side):
    player_name = current_players[side]
    score[player_name] += 1

Dictionaries still work really well.

Caleb Hattingh
  • 9,005
  • 2
  • 31
  • 44
0

I would consider your second approach dangerous! Noone (including you in two month) will get the logic and understand your code.

Sometimes, logical AND can be your friend:

if (self.player.side == 'left')  and (side == 'left'):  self.enemy.score += 1
if (self.player.side == 'left')  and (side == 'right'): self.player.score += 1
if (self.player.side == 'right') and (side == 'left'):  self.player.score += 1
if (self.player.side == 'right') and (side == 'right'): self.enemy.score += 1

looks much more tidy and the logic is crystal clear.

OBu
  • 4,977
  • 3
  • 29
  • 45