Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling Different Functions in Python Based on Values in a List

I have a script that takes a list of metrics as an input, and then fetches those metrics from the database to perform various operations with them.

My problem is that different clients get different subsets of the metrics, but I don't want to write a new IF block every time we add a new client. So right now, I have a large IF block that calls different functions based on whether the corresponding metric is in the list. What is the most elegant or Pythonic way of handling this?

Setup and function definitions:

clientOne = ['churn','penetration','bounce']
clientTwo = ['engagement','bounce']

def calcChurn(clientId):
    churn = cursor.execute(sql to get churn)
    [...]
    return churn

def calcEngagement(clientId):
    engagement = cursor.execute(sql to get engagement)
    [...]
    return engagement

Imagine three other functions in a similar format, so there is one function that corresponds to each unique metric. Now here is the block of code in the script that takes the list of metrics:

def scriptName(client, clientId):
    if churn in client:
        churn = calcChurn(clientId)
    if engagement in client:
        engagement = calcEngagement(clientId)
    if penetration in client:
    [...]
like image 798
dsal1951 Avatar asked May 18 '15 00:05

dsal1951


People also ask

Can you call functions from a list in Python?

Answer. Yes, the variable in the for of a list comprehension can be used as a parameter to a function.

Can functions call other functions in Python?

In Python, any written function can be called by another function. Note that this could be the most elegant way of breaking a problem into chunks of small problems.


2 Answers

Generally, you'd create a mapping of names to functions and use that to calculate the stuff you want:

client_action_map = {
  'churn': calcChurn,
  'engagement': calcEngagement,
  ...
}

def scriptName(actions, clientId):
    results = {}
    for action in actions:
        results[action] = client_action_map[action](clientId)
    return results
like image 158
mgilson Avatar answered Sep 21 '22 14:09

mgilson


You can create a class with static methods and use getattr to get the correct method. It's similar to what mgilson suggests but you essentially get the dict creation for free:

class Calculators:

    @staticmethod
    def calcChurn():
        print("called calcChurn")

    @staticmethod
    def calcEngagement():
        print("called calcEngagement")

    @staticmethod
    def calcPenetration():
        print("called calcPenetration")

stats = ["churn", "engagement", "penetration", "churn", "churn", "engagement", "undefined"]

def capitalise(str):
    return str[0].upper() + str[1:]

for stat in stats:
    try:
        getattr(Calculators, "calc" + capitalise(stat))()
    except AttributeError as e:
        print("Unknown statistic: " + stat)

called calcChurn
called calcEngagement
called calcPenetration
called calcChurn
called calcChurn
called calcEngagement
Unknown statistic: undefined

like image 33
Raniz Avatar answered Sep 18 '22 14:09

Raniz