Question

everyone. Please see example below. I'd like to supply a string to 'schedule_action' method which specifies, what Bot-class method should be called. In the example below I've represented it as 'bot.action()' but I have no idea how to do it correctly. Please help

class Bot:
    def work(self): pass
    def fight(self): pass

class Scheduler:
    def schedule_action(self,action):
       bot = Bot()
       bot.action()

scheduler = Scheduler()
scheduler.schedule_action('fight')
Was it helpful?

Solution

Use getattr:

class Bot:
    def fight(self):
       print "fighting is fun!"

class Scheduler:       
    def schedule_action(self,action):
       bot = Bot()
       getattr(bot,action)()

scheduler = Scheduler()
scheduler.schedule_action('fight')

Note that getattr also takes an optional argument that allows you to return a default value in case the requested action doesn't exist.

OTHER TIPS

In short,

getattr(bot, action)()

getattr will look up an attribute on the object by name -- attributes can be data or member methods The extra () at the end calls the method.

You could get the method in a separate step, like this, as well:

method_to_call = getattr(bot, action)
method_to_call()

And you can pass arguments to the method in the usual way:

getattr(bot, action)(argument1, argument2)

or

method_to_call = getattr(bot, action)
method_to_call(argument1, argument2)

I'm not sure if it applies in your situation, but you may consider using a function pointer instead of manipulating the strings.

class Bot:
    def work(self): 
        print 'working'
    def fight(self): 
        print 'fightin'

class Scheduler:
    def schedule_action(self,action):
       bot = Bot()
       action(bot)

scheduler = Scheduler()
scheduler.schedule_action(Bot.fight)
scheduler.schedule_action(Bot.work)

Which prints:

fightin
working

If you can do this, it will give you an error about a misspelled function at compile-time when the code is interpreted instead of during run-time. This could shorten your debug cycle for stupid data-entry errors, especially if the actions are done over a span of time. Nothing sucks more than running something overnight and discovering that you had a syntax error in the morning.

class Scheduler:
    def schedule_action(self,action):
       bot = Bot()
       boundmethod = getattr(bot, action)
       boundmethod()
def schedule_action(self,action):
         bot = Bot()
         bot.__getattribute__(action)()

You can also use a dictionary to map methods to actions. For instance:

ACTIONS = {"fight": Bot.fight,
           "walk": Bot.walk,}

class Scheduler:
    def schedule_action(self, action):
        return ACTIONS[action](Bot())
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow