我有一个脚本,它将度量列表作为输入,然后从数据库中提取这些度量以使用它们执行各种操作。
我的问题是不同的客户端获得指标的不同子集,但我不想在每次添加新客户端时编写新的IF块。所以现在,我有一个大的IF块,根据相应的度量是否在列表中调用不同的函数。什么是最优雅或 Pythonic 处理此方法?
设置和功能定义:
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
想象一下类似格式的其他三个函数,因此有一个函数对应于每个唯一度量。现在这里是脚本中的代码块,它包含指标列表:
def scriptName(client, clientId):
if churn in client:
churn = calcChurn(clientId)
if engagement in client:
engagement = calcEngagement(clientId)
if penetration in client:
[...]
答案 0 :(得分:10)
通常,您要创建名称到函数的映射,并使用它来计算您想要的东西:
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
答案 1 :(得分:3)
您可以使用静态方法创建一个类,并使用getattr
来获取正确的方法。它与mgilson建议的类似,但你基本上可以免费获得dict:
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)
叫做calcChurn
叫做calcEngagement
叫做calcPenetration
叫calcChurn
叫calcChurn
叫做calcEngagement
未知统计数据:未定义
答案 2 :(得分:0)
将所需的调用封装在对象中也许是有意义的。
如果您的客户端成为对象是有意义的,特别是如果许多客户端调用相同的函数集来获取指标,那么您可以创建一组Client
子类,这些子类调用预定义的一组获取指标的功能。
它比映射字典重一点。
''' Stand alone functions for sql commands.
These definitions however dont really do anything.
'''
def calc_churn(clientId):
return 'result for calc_churn'
def calc_engagement(clientId):
return 'result for calc_engagement'
''' Client base object '''
class Client(object):
''' Base object allows list of functions
to be stored in client subclasses'''
def __init__(self, id):
self.id = id
self.metrics = []
self.args = []
def add_metrics(self, metrics, *args):
self.metrics.extend(metrics)
self.args = args
def execute_metrics(self):
return {m.__name__: m(*self.args) for m in self.metrics}
''' Specific sub classes '''
class Client1(Client):
def __init__(self, id):
''' define which methods are called for this class'''
super(Client1, self).__init__(id)
self.add_metrics([calc_churn], id)
class Client2(Client):
def __init__(self, id):
''' define which methods are called for this class'''
super(Client2, self).__init__(id)
self.add_metrics([calc_churn, calc_engagement], id)
''' create client objects and '''
c1 = Client1(1)
c2 = Client2(2)
for client in [c1, c2]:
print client.execute_metrics()
您将从execute_metrics
获得的结果是dict
将函数名称映射到该客户端的结果。