4

Instead of doing a long if..elif, is there a way to store code in a list or dictionary to be run? Something like:

my_dict = {'up': 'y=y+1', 'down': 'y=y-1', 'left': 'x=x-1', 'right': x=x+1'}

Then you match up the choice to the dict and run the result?

Or is the next best thing to a traditional if..elif chain a conditional expression:

x = x+1 if choice == 'right' else x-1 if choice == 'left' else x
y = y+1 if choice == 'up' else y-1 if choice == 'down' else y

Part of the reason I am asking, apart from sheer curiosity, is that I am writing a game in Pygame to help learn Python coding. I have 12 keys I am checking for being pressed, and I am using a very long and ungainly if..elif structure that makes me think there has to be a more beautiful way of doing it. Basically what I have looks like this:

for event in pygame.event.get():
        if event.type == pygame.QUIT:
            crashed = True
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_t:
                red += 10
            elif event.key == pygame.K_g:
                red -= 10
            elif event.key == pygame.K_5:
                red += 1
            elif event.key == pygame.K_b:
                red -= 1
            elif event.key == pygame.K_y:
                green += 10
            elif event.key == pygame.K_h:
                green -= 10
            elif event.key == pygame.K_6:
                green += 1
            elif event.key == pygame.K_n:
                green -= 1
            elif event.key == pygame.K_u:
                blue += 10
            elif event.key == pygame.K_j:
                blue -= 10
            elif event.key == pygame.K_7:
                blue += 1
            elif event.key == pygame.K_m:
                blue -= 1

Is that what my Python code is supposed to look like? Or is there a more Pythonic way to code this?

TigerhawkT3
  • 48,464
  • 6
  • 60
  • 97
Sindyr
  • 1,277
  • 1
  • 11
  • 16
  • 2
    You can put functions into any variable, including as a value in a `dict`. Or even as a key, but you don't want that :). – Cyphase Aug 15 '15 at 21:33
  • 2
    There's not much you can do about things like arbitrary key commands/actions. Using an `if..elif` structure is a fine way to do it. – TigerhawkT3 Aug 15 '15 at 21:36
  • see if [this SO QA](http://stackoverflow.com/questions/60208/replacements-for-switch-statement-in-python) helps – Pynchia Aug 15 '15 at 21:44
  • see the updated accepted answer for further info and example use – Nikos M. Aug 16 '15 at 16:36

2 Answers2

2

Yes, there is a way but by using functions:

def up():
    y=y+1

def down():
    y=y-1

def left():
    x=x-1

def right():
    x=x+1


d = {'up': up, 'down': down, 'left': left, 'right': right};

then call it like d['up']().

To avoid using global variables, you may use OOP approach:

class player:
    def __init__(self, x=0, y=0):
       self.x = x
       self.y = y

    def up(self):
        self.y += 1

    def down(self):
        self.y -= 1

    def left(self):
        self.x -= 1

    def right(self):
        self.x += 1

    def move(self, direction):
        # call the appropriate method that corresponds to given direction
        getattr(self, direction)()

Example use:

p = player(0,0)
p.move('up') # and so on..
Nikos M.
  • 8,033
  • 4
  • 36
  • 43
Assem
  • 11,574
  • 5
  • 59
  • 97
2

For this situation, one way to do it is to store the values you want to add/subtract in the dictionary, then retrieve them and add them. Something like this:

offsets = {
    'up': (0, 10),
    'down': (0, -10),
    'left': (-10, 0),
    'right': (10, 0)
}
xOffset, yOffset = offsets[choice]
x += xOffset
y += yOffset

You can store functions in a dictionary, but the functions won't be able to modify variables of their calling context. If you find that the "code snippets" you are storing all have the same structure (as here where each is "add something to x" or "add something to y"), what you may be able to do is factor out that code into one place, and only store the parameters in the dictionary (as here where you can store the values you want to add).

BrenBarn
  • 242,874
  • 37
  • 412
  • 384