0
\$\begingroup\$

I have this function in python:

def executecommand(call):
    if call.data == "/getpair":
        return getpaircmd(call.message)
    elif call.data == "/menu":
        return menucmd(call.message)
    elif call.data == "/setalarm":
        return setalarmcmd(call.message)

And I was hoping to replace it with object and .get(call.data) message, like this:

def executecommand(call):
    return {
        "/getpair": getpaircmd(call.message),
        "/menu": menucmd(call.message),
        "/setalarm": setalarmcmd(call.message)
    }.get(call.data)

But it seems like it calls every function on the list.

So, is there a way to simplify it?

\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

The parentheses act as a function-calling operator in Python. Therefore, your attempt to build the dispatch table would end up calling all the functions. What you can do instead is this:

def executecommand(call):
    return {
        "/getpair": getpaircmd,
        "/menu": menucmd,
        "/setalarm": setalarmcmd,
    }[call.data](call.message)

Note that the behavior with the lookup table is different from the original in the case where call.data is not one of the expected choices. In your code unknown messages will be ignored, in the example code above it would raise a TypeError because the dictionary would return None, which is not callable.

I also recommend putting a comma consistently, so that if you later add or remove a command, you'll get cleaner diffs in your source code version control.

The fact that you see all the functions being called highlights a potential performance issue: the dispatch table is rebuilt every time executecommand() runs. The table should be built just once:

_DISPATCH = {
    "/getpair": getpaircmd,
    "/menu": menucmd,
    "/setalarm": setalarmcmd,
}

def executecommand(call):
    return _DISPATCH[call.data](call.message)
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.