如何干净地处理彼此非常相似的多个条件

How to cleanly handle multiple conditions that are very similar to one another

我正在尝试找到一种方法来最好地处理彼此非常相似的多个路径文件。虽然我的代码有效,但我觉得如果不进行大量手动工作,它会很麻烦、更难维护且难以扩展(例如,假设我需要不断添加越来越多的路径,这些路径只是略有不同。

理想情况下,如果有更好的解决方案,我希望尽可能多地应用 DRY 原则,而不是到处都是 if-else 语句。

我认为使用字典或 class 可能会有一些改进,但将路径也存储在字典中感觉很麻烦。我对 classes 没有那么丰富的经验,所以如果没有大量的解决方法我无法让它工作(我认为我没有正确构建 class)

代码

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

路径没有问题,按预期工作。我相信可以通过重构来改进代码,但是,我不确定在不重复的情况下处理非常相似的条件的最佳方法。

您可以使用包含符合您条件的键的字典:

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

一般来说,在这种情况下有时很难避免代码重复。您可以使用字典和棘手的 类 来生成特殊类型的条件,但对于这么简单的情况通常不值得这样做。它会使您的代码可读性降低,可读性很重要。

相反,坚持使用更简单的技术。我可能会为您的代码推荐三种优化方法。

首先,您可以用更高级的格式字符串替换内部条件。使用 '{month:0>2}'.format(month=n) 将用零填充任何 one-digit 个月。 (0 表示用零填充,> 表示 right-align,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))