Самый эффективный способ обработки большого количества констант - PullRequest
0 голосов
/ 11 марта 2019

Я пишу программу, которая, в зависимости от определенных значений из таблицы 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 ...

...

Может быть, есть лучший способ справиться с этим?

Ответы [ 2 ]

2 голосов
/ 11 марта 2019

Один из способов - сопоставить константы с соответствующими обработчиками:

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 есть в вашем случае? Также обратите внимание, что english и russian являются автономными функциями. Наконец, класс 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. Если действие не зависит одновременно от provider и language, в этом случае вам нужна двойная карта:

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]
    ...
0 голосов
/ 11 марта 2019

Сочетание языка и поставщика может составить имя метода, и вызов будет вызван динамически.

Пример:

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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...