【问题标题】:Most efficient way to handle big number of constants处理大量常量的最有效方法
【发布时间】:2019-03-11 10:45:31
【问题描述】:

我正在编写一个程序,该程序根据 Excel 表中的某些值进行 API 调用。将检查表中的 2 个条件:

  • 语言
  • 提供者

根据这两个值,API 调用需要一组不同的常量:

def run_workflow(provider, language, workflow):

    if provider == 'xxxx' and language == 0:

    wf_ready = provider_ready
    wf_unverified = provider_unverified
    wf_active = provider_active
    wf_another = provider_another
    wf_closed = provider_closed
    wf_wrongid = provider_wrongid

    elif provider == 'yyyy' and language == 0:

    wf_ready = provider_ready
    wf_unverified = provider_unverified
    wf_active = provider_active
    wf_another = provider_another
    wf_closed = provider_closed
    wf_wrongid = provider_wrongid

    elif ...


    if workflow == 'ready':
    response = requests.post(API + wf_ready),headers=header, data=json.dumps(conversation))

    elif workflow == 'unverified':
    response = requests.post(API + wf_unverified),headers=header, data=json.dumps(conversation))

    elif ...

有 2 种提供者和 7 种不同的语言,我试图找出处理这种情况的最有效(和 Pythonic 方式)并想出为每种语言创建一个类:

class Workflow_Language():

  def english(self):

    self.provider_unverified = 1112
    self.provider_ready = 1113
    self.provider_active = 1114
    self.provider_vip = 1115

  def russian(self):

    self.provider_unverified = 1116
    self.provider_ready = 1117
    self.provider_active = 1118
    self.provider_vip = 1119

  def ...

...

有没有更好的方法来处理这个问题?

【问题讨论】:

  • 也许从某种配置文件中读取这些值。

标签: python python-3.x function class


【解决方案1】:

一种方法是将常量映射到适当的处理程序:

class LanguageData:
    def __init__(self, unverified, ready, active, vip):
        self.unverified = unverified
        self.ready = ready
        self.active = active
        self.vip = vip

def english():
    return LanguageData(1,2,3,4)

def russian():
    return LanguageData(5,6,7,8)

LANGUAGE_MAP = {'en': english, 'ru': russian}

为了清楚起见,我编造了'en', 'ru' 值。你的情况似乎是0?另请注意,englishrussian 是独立函数。最后,LanguageData 类不是强制性的,您可以简单地从这些函数中返回一个字典。但是使用属性而不是字符串键似乎更容易维护。

然后在代码中:

def run_workflow(provider, language, workflow):
    lang_data = LANGUAGE_MAP[language]()
    if workflow == 'ready':
        url = API + data.ready
    elif workflow == 'unverified':
        url = API + data.unverified
    response = requests.post(url, headers=header, data=json.dumps(conversation))

当然,workflow 如果有超过 2 个可能的值,也可以用类似的方式包装。

类似于provider。除非动作同时依赖于providerlanguage,在这种情况下你需要一个双映射:

LANG_PROV_MAP = {
    ('en', 'xxxx'): first,
    ('ru', 'yyyy'): second,
}
def run_workflow(provider, language, workflow):
    data = LANG_PROV_MAP[(provider, language)]()
    ...

原始代码可以用一个棘手的装饰器来简化:

LANGUAGE_MAP = {}
def language_handler(lang):
    def wrapper(fn):
        LANGUAGE_MAP[lang] = fn
        return fn
    return wrapper

@language_handler('en')
def handler():
    return LanguageData(1,2,3,4)

@language_handler('ru')
def handler():
    return LanguageData(5,6,7,8)

还要注意,如果数据是“恒定的”(即不依赖于上下文),那么您可以完全省略可调用对象以使一切变得更简单:

LANGUAGE_MAP = {
    'en': LanguageData(1,2,3,4),
    'ru': LanguageData(5,6,7,8),
}
def run_workflow(provider, language, workflow):
    data = LANGUAGE_MAP[language]
    ...

【讨论】:

  • @brunodesthuilliers 我已经在我的回答中添加了使用字典的可能性。但是使用字符串键通常比使用属性更难。我建议使用课程。对于初学者来说,现在大多数 IDE 都支持类,这与任意字典完全不同。类还可以很好地与现代提示和静态分析配合使用。
  • 确实——但是可以更容易地使用 dict 作为关键字 args 或作为请求的参数(get 或 post)传递。现在你当然也可以在类中添加to_dict 方法...
  • @freakish 非常感谢!这已经帮助了我很多。但是,我没有提到我必须同时检查语言和提供者。所以,我有 2 个提供者,对于每个提供者,每种语言都有 2 组工作流(常量)。仍然不确定这可能是这种情况的最佳解决方案。目前我认为最好只使用两个地图(LANGUAGE_MAP_PROVIDER1 和 LANGUAGE_MAP_PROVIDER2)?由于数据是不变的,我会跳过你在上一个例子中展示的可调用对象,但是有两个地图呢?
【解决方案2】:

语言和提供者的组合可以组成方法名,调用将被动态调用。

例子:

import sys

def provider1_lang2():
    pass

def provider2_lang4():
    pass

 # get the provider / lang and call the method dynamically
 provider = 'provider2'
 lang = 'lang4' 
 method_name = '{}_{}'.format(provider,lang)
 method =  getattr(sys.modules[__name__], method_name)
 method()

【讨论】:

  • 最好使用字典 - 更明确、更不容易出错、更易于阅读和维护等。
猜你喜欢
  • 1970-01-01
  • 2020-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多