1

I'm refactoring some code that a friend wrote and recently stumbled across this function:

def setup_parameters(self, data):
    '''Parse raw data to determine game settings.'''
    for line in data.split('\n'):
      line = line.strip().lower()
      if line:
        tokens = line.split()

        self.L.debug("tokens: " + str(tokens))

        key = tokens[0]
        if key == 'cols':
          self.width = int(tokens[1])
        elif key == 'rows':
          self.height = int(tokens[1])
        elif key == 'player_seed':
          random.seed(int(tokens[1]))
        elif key == 'turntime':
          self.turntime = int(tokens[1])
        elif key == 'loadtime':
          self.loadtime = int(tokens[1])
        elif key == 'viewradius2':
          self.viewradius2 = int(tokens[1])
        elif key == 'attackradius2':
          self.attackradius2 = int(tokens[1])
        elif key == 'spawnradius2':
          self.spawnradius2 = int(tokens[1])

As you can see, there is a nasty kind of switch statement here, that clearly calls for a dictionary. I'm tempted to write this as a class dictionary since the keys are constant, but since the keys map to attributes of an instance (ie, 'cols': self.width) this doesn't compile.

My question is then, what is the right way to refactor such code?

Ceasar
  • 22,185
  • 15
  • 64
  • 83
  • Duplicate question: http://stackoverflow.com/questions/60208/replacements-for-switch-statement-in-python – JBernardo Sep 09 '11 at 19:02
  • 1
    Seeing that you are taking the effort of refactoring that code I suggest you take a look and use the standard python ConfigParser module – fabrizioM Sep 09 '11 at 19:55

3 Answers3

6

Map the keys to the names of the attributes, and use setattr(self, attribute_name, int(tokens[1]) to set the value. E.g.:

attribute_dict = dict(cols="width", rows="height", turntime="turntime", ...)
[...]
value = int(tokens[1])
if key == "player_seed":
    random.seed(value)
else:
    setattr(self, attribute_dict[key], value)
Tamás
  • 47,239
  • 12
  • 105
  • 124
1

You can build up a dictionary with the keys as accessors and lambda functions to execute the code for each key.

Burton Samograd
  • 3,652
  • 19
  • 21
1

setup a dict with actions like

actions = dict(cols = lambda tokens: setattr(self, "width", int(tokens[1]), ... 
               player_seed = lambda tokens: random.seed(int(tokens[1]))
              )

and then:

 actions[key](tokens)
rocksportrocker
  • 7,251
  • 2
  • 31
  • 48