Jon
Jon

Reputation: 139

Using user input to call functions

I was trying to make a "game" in Python where the user inputs a command. However, I do not know whether you can take that input to be a function name. This is my current effort:

def move():
    print("Test.")

if __name__ == "__main__":
    input("Press enter to begin.")
    currentEnvironment = getNewEnvironment(environments)
    currentTimeOfDay = getTime(timeTicks, timeOfDay)
    print("You are standing in the {0}. It is {1}.".format(currentEnvironment, currentTimeOfDay))
    command = input("> ")
    command()

Here, the input was move, as I wanted to try and call that function (as a potential end user might). However, I get the following error:

Traceback (most recent call last):
  File "D:\Text Adventure.py", line 64, in <module>
    command()
TypeError: 'str' object is not callable

I was wondering if there was any way that I could allow a user to 'move' in the game, which the program achieves by calling the "move" function.

Upvotes: 2

Views: 40172

Answers (4)

mgilson
mgilson

Reputation: 309929

It looks like you're using python3.x where input returns a string. To recover the python2.x behavior, you need eval(input()). However, you shouldn't do this. It's likely to lead to a bad day.


A better idea is to put the functions into a dictionary --

def move():
    #...

def jump():
    #...

function_dict = {'move':move, 'jump':jump }

and then:

func = input('>')  #raw_input on python2.x
function_dict[func]()

The following code works for me on python3.2.

def move():
    print("Test.")

func_dict = {'move':move}
if __name__ == "__main__":
    input("Press enter to begin.")
    currentEnvironment = "room" #getNewEnvironment(environments)
    currentTimeOfDay = "1 A.M." #getTime(timeTicks, timeOfDay)
    print("You are standing in the {0}. It is {1}.".format(currentEnvironment, currentTimeOfDay))
    command = input("> ")
    func_dict[command]()

Upvotes: 7

Dave
Dave

Reputation: 3956

It's usually better to re-use code as Hans suggests, but if you wanted to input commands and run them manually, it would be MUCH safer to have a dictionary of valid commands than to directly execute user-provided input.

cmd = { 'move': move, 'jump': jump, 'look': look }

Upvotes: 0

Hans Then
Hans Then

Reputation: 11322

Have a look at the cmd module. See this.

It is normally used for shell style comman dlanguages, but it can also be used to create simple text style adventure games.

You can create commands by creating a new method on the Cmd subclass.

E.g.

def do_move(self, args):
    if self.next_room.has_snake():
        print "The next room contains a poisonous snake. It bites you and you die."
    else:
        print "The room is empty"

Upvotes: 2

georg
georg

Reputation: 214969

You can access functions by name using:

function = globals()[function_name]

if the function is in the current module, or

function = getattr(other_module, function_name)

You should also take measures to disallow calling arbitrary functions, for example, prefixing:

 def cmd_move() # ok to call this
 def cmd_jump() # ok to call this

 def internal_func....

 cmd = raw_input('>') # e.g. "move"
 fun = globals()['cmd_' + cmd]
 fun()

Upvotes: 2

Related Questions