[Tutor] Help with classes

Alan Gauld alan.gauld at freenet.co.uk
Thu Apr 7 23:14:23 CEST 2005

> I am fooling around with classes and I was trying to create a very
> small one player text adventure. I made a class called commands here
> it is:

OK, recall that a class represents a template from which you
create (one or) many instances. Thus any class that is named in
the plural usually indicates a problem in the design. You
will only have one instance of your class, only one object.

If you use the singlular version, your class will be Command,
and then you can have many instances, one for each command.
But you want each command to do something different - so
you need subclasses of Command, each one responding to a
single command.

Something like:

class Command:
  def doit(self):   # just a placeholder
    print 'Not built yet'

class Quit(Command):
  def doit(self):   # this is polymorphism
     raise SystemExit

class Help(Command):
   def doit(self):
       answer = None
       i = ['look','get','take','kill','drink','eat','eq','help']
       while not answer in i:
          answer = raw_input(response)
          #Help files will go here
          return answer

That of course requires more typing but it does mean you can add
new commands without changing (and maybe breaking) the existing
working commands. Also any common command code can be added to
the Command class and picked up by all the existing command
subclasses. Also you could, for example define a method that
returns a string describing the class. Then your help method
can simply call the appropriate class's describe method. That
way you never need to create separate help files with the
risk of inconsistencies developing or files going missing.

> while 1:
>     com = Commands()

Now instead of instantiating your single instance you can create
a dictionary of command strings and the corresponding command:

     commands = {
          'look'    :    Command()
          'get'     :    Command()
          'take'    :    Command()
          'kill'    :    Command()
          'drink'   :    Command()
          'eat'     :    Command()
          'eq'      :    Command()
          'help'    :    Help()
          'quit'    :    Quit()

And now the user can select from the set of keys

for command in command.keys():
    print command

Now read the choice and call the appropriate command object.

>     command = raw_input(">>>: ")
>     if command not in commands.keys:
>         print "\nI don't understand that command?\n"
      else: commands[command].doit()

> shorter way to write it but the only way I can think of is with an
> statment for each command. Is there a better way or shorter way to
> this?

The dictionary approach above is extendable and minimises changes
to working code. As you define new Command classes just change the
corresponding dictionary entry.

[There is a more elegant technique yet that involves making the
classes callable and self describing, but this is OK for now...]


Alan G
Author of the Learn to Program web tutor

More information about the Tutor mailing list