什么是使用标志来(de)激活方法中的功能的Pythonic方法?

时间:2015-09-26 00:42:05

标签: python python-2.7

我想自定义一些代码。假设我想将一堆学生应用程序分配给暑期课程给各种读者(所以100个应用程序,3个读者,大致均匀划分等)。在某些情况下,我想考虑读者偏好(我只想阅读加州学生的申请等)。在其他情况下,我不关心他们被分配到谁。现在我有一些看起来像这样的东西:

def assign_readers(preferences_flag): 
    if preferences_flag:
        assign_readers_with_preferences()
    assign_remaining 

我在我的代码中有多个类似功能的情况,我希望能够轻松打开/关闭,但它看起来不像是一种必要的干净方式。有时在代码的其他部分使用相同的标志,所以我左右传递这些标志。例如:

def log_reader_stats(preferences_flag, other_flag):
    if preferences_flag: 
        log_reader_stats_with_preferences()
    if other_flag:
        log_readers_stats_with_other_stuff()
    log_remaining_stats

这样做的替代方法是什么?传递标志似乎重复和低效,但除此之外,我不知道如何打开和关闭这些功能。

下面是一些如何使用实际代码以及标志如何发挥作用的示例。

USE_PREF = True
USE_SPEC_GRP = True

def main(): 
    # Load and store config file information 
    fnames = {} 
    snames = {} 
    options = read_config_file()
    validate_config_params(options, fnames, snames)


    # Load the applications file
    apps = pio.file_to_frame(fnames["apps"], snames["apps"])

    # load target and max number of apps each reader can handle.
    rdr_counts = pio.file_to_frame(fnames["rdr_counts"], snames["rdr_counts"])

    # Assign applications depending on which options are enabled
    if USE_SPEC_GRP:
        assign_all_special_groups(apps, fnames["spec_grp"], snames["spec_grp"])

    if USE_PREF: 
        assign_apps_with_prefs(apps, rdr_counts, 
                                fnames["rdr_prefs"], snames["rdr_prefs"])
    assign_remaining_apps(apps, rdr_counts, fnames, snames)

3 个答案:

答案 0 :(得分:2)

虽然你没有提出这个问题,但有一个code smell需要解释。每当您发现自己使用fnamessnames等并行数据源时:

assign_all_special_groups(apps, fnames["spec_grp"], snames["spec_grp"])

您通常会制作容易出错的代码。相反,你可以

names['spec_grp'] = ('something', 'anotherthing')

确保spec_grp的元素始终保持相互关联。存在namedtuple type,使访问非常易读:

names['spec_grp'].f_thing
names['spec_grp'].s_thing

但如果没有轻微的复杂性,您需要使用

访问它们
names['spec_grp'][0]
names['spec_grp'][1]

如果我正确地阅读你的意图,上面的代码可以将这些值与选项标志组合起来,以便

 options['spec_grp'] = (fname_for_spec_grp, sname_for_spec_group)
 if options['spec_grp']:
    assign_all_special_groups(apps, options["spec_grp"][0], options["spec_grp"][1])

这使初始化没有None值的配置元素变得很重要,但这也是一种很好的做法。

但是我没有让你的通话代码更长更难读?均田。是否为一些额外角色为您带来了灵活性,可维护性和安全性?是的。它确实将三个数据结构(选项,fnames,snames)转换为一个字典,表示是否需要一个选项,如果需要,它的参数是什么。

答案 1 :(得分:1)

您只需创建一个包含属性 PhoneValue=0 if (condition== "new"): PhoneValue=int(PhoneValue+10) else: PhoneValue=int(PhoneValue+9) if GPS==bool(input("true")): PhoneValue=int(PhoneValue+1) else: PhoneValue=int(PhoneValue) if WiFi==eval(bool(input("true"))): PhoneValue=int(PhoneValue+1) else: PhoneValue=int(PhoneValue) if camera==eval(bool(input("true"))): PhoneValue=int(PhoneValue+1) else: PhoneValue=int(PhoneValue) global PhoneValue 的类ReadersManager,制作该类的函数方法并访问其中的flags

答案 2 :(得分:1)

最好的方法是看看其他人是如何做到的,在这种情况下是ConfigParser standard module。这使用字典来存储和检索配置数据(实际上它使用字典的字典,但我们不需要)。关键是字典可以将名称与大多数内容相关联,使用数据来描述数据的位置远比硬编码更好。

在您的情况下,字典

options = {
    'USE_SPEC_GROUP': False,
    'USE_PREF': False,
} 

但它是一本字典,所以我可以根据需要添加它

 options['available'] = False

甚至可以轻松进行批量初始化:

 options = {}
 for option in "car plane train boat".split():
     options[option] = False

当然在条件中访问它们很容易

 if options['boat']:
     # do boat things

现在你有一个传递包含所有配置数据的变量:

some_function(options)

当像dict这样的基本类型本身非常有用时,无需使用类。