Как правильно обрабатывать несколько состояний, которые очень похожи друг на друга - PullRequest
0 голосов
/ 27 июня 2019

Я пытаюсь найти способ наилучшей обработки файлов с несколькими путями, которые очень похожи друг на друга. Хотя мой код работает, я чувствую, что он громоздок, сложен в обслуживании и труден для масштабирования без большого количества ручной работы (например, предположим, мне нужно продолжать добавлять все больше и больше путей, которые немного отличаются.

В идеале, я хотел бы как можно больше применять принцип СУХОЙ и не иметь повсеместных утверждений if-else, если есть лучшее решение.

Я подумал, что использование словарей или классов может быть некоторым улучшением, но было неудобно также хранить пути в словаре. Я не так опытен с классами, поэтому я не смог заставить его работать без тонны обходных путей (я не думаю, что я правильно строил класс)

Код

def save_df(df, banner, year, month):
    base_path = r'common\path\{0}\for\all\banners\{1}'.format(banner.upper(), year)

    if banner in ('a', 'b'):
        if month < 10:
            # The zero is so I can have the file month in '01, 02, etc.' format
            default_path = os.path.join(base_path, '{0}-0{1}_TEST'.format(year, month))
        else:
            default_path = os.path.join(base_path, '{0}-{1}_TEST'.format(year, month))
    else:
        if month < 10:
            default_path = os.path.join(base_path, '{0}_{1}-0{2}_TEST'.format(banner.upper(), year, month))
        else:
            default_path = os.path.join(base_path, '{0}_{1}-{2}_TEST'.format(banner.upper(), year, month))

    saved_output = [df, default_path]
    return saved_output

Нет проблем для пути, работает как задумано. Я считаю, что код может быть улучшен путем рефакторинга, однако я не уверен, что лучше всего работать с условиями, которые очень похожи без повторения.

Ответы [ 2 ]

0 голосов
/ 27 июня 2019

В общем, иногда бывает трудно избежать дублирования кода в подобных случаях.Вы можете использовать словари и хитрые классы для генерации специальных типов условий, но это обычно не стоит в таком простом случае.Это может сделать ваш код менее читабельным, а читабельность важна.

Вместо этого придерживайтесь более простых методов.Я могу порекомендовать вам три оптимизации для вашего кода.

Во-первых, вы можете заменить внутреннее условное выражение на более сложную строку формата.Использование '{month:0>2}'.format(month=n) будет дополнять любые однозначные месяцы нулем.(0 говорит о заполнении нулями, > говорит о выравнивании по правому краю, а 2 говорит о заполнении как минимум до 2 цифр.)

Во-вторых, вы можете сделать что-то подобное свнешнее условие: используйте переменную banner.upper() + '_' в одном случае и пустую строку в другом случае.

В-третьих, вы можете написать функцию для тела ветвей, но это не такдействительно необходимо после двух других моих предложений.

def format_path(fmt, year, month, banner=None):
    if banner is None:
        banner = ''
    else:
        banner = banner.upper() + '_'
    return os.path.join(base_path, '{}{}-{:0>2}'.format(banner, year, month))
0 голосов
/ 27 июня 2019

Вы можете использовать словарь с ключами, которые соответствуют вашим условиям:

import os

def save_df(df, banner, year, month):
    base_path = r'common\path\{0}\for\all\banner\{1}'.format(banner.upper(), year)

    # Each key is a tuple, left key is True if month is less than 10, 
    # right key is True if banner is equal to 'a' or 'b'
    formats = { # Key: (month_less_10, a_b_banner)
      (True, True): '{0}-0{1}_TEST'.format(year, month),
      (False, True): '{0}-{1}_TEST'.format(year, month),
      (True, False): '{0}_{1}-0{2}_TEST'.format(banner.upper(), year, month),
      (False, False): '{0}_{1}-{2}_TEST'.format(banner.upper(), year, month)
    }
    default_path = os.path.join(base_path, formats[(month < 10, banner in ('a', 'b'))]

    saved_output = [df, default_path]
    return saved_output
...