Search code examples
pythonpython-3.xlocals

Python: random function from locals() with defined prefix


I'm working on a textbased adventure and now want to run a random function. All adventure function are "adv" followed by a 3 digit number.
If I run go() I get back :

IndexError: Cannot choose from an empty sequence

This is because allAdv is still empty. If i run go() line by line in the shell it works but not in the function. What did I miss?

import fight
import char
import zoo
import random

#runs a random adventure
def go():
    allAdv=[]
    for e in list(locals().keys()):
        if e[:3]=="adv":
            allAdv.append(e)
    print(allAdv)
    locals()[random.choice(allAdv)]()


#rat attacks out of the sewer
def adv001():
    print("All of a sudden an angry rat jumps out of the sewer right beneath your feet. The small, stinky animal aggressivly flashes his teeth.")
    fight.report(zoo.rat)

Solution

  • It's mainly due to the scope issue, when you invoke locals() in go(), it only prints out the local variables allDev defined in this function:

    locals().keys()  # ['allDev']
    

    But if you type the following line by line in the shell, locals() do include adv001 since they are at the same level in this case.

    def adv001():
        print("All of a sudden an angry rat jumps out of the sewer right beneath your feet. The small, stinky animal aggressivly flashes his teeth.")
        fight.report(zoo.rat)
    
    allAdv=[]
    print locals().keys()  #  ['adv001', '__builtins__', 'random', '__package__', '__name__', '__doc__']
    for e in list(locals().keys()):
        if e[:3]=="adv":
            allAdv.append(e)
    print(allAdv)
    locals()[random.choice(allAdv)]()
    

    If you really want to get those function variables in go(), you might consider change locals().keys() to globals().keys()