如何避免在Python字典中重复的if语句

1 投票
2 回答
1707 浏览
提问于 2025-04-17 02:49

我正在尝试根据用户提交的HTML表单数据创建一个新的字典。结果我写了很多重复的if语句,检查某个键(比如xyz)是否在表单数据的字典里。我知道这样做效率不高,但我不太确定该如何用Python来实现。

这是表单数据的字典:

form_data = {
'urls': ['www.google.com', 'www.bing.com'],
'useremail': ['my@email.com'],
'emailfield': ['1'],
'addressfield': ['1'],
'addressfield_info':['Company'],
'addressfield_instruction': ['Please only if the company is a LLC'],
'phonefield': ['1'],
'phonefield_instruction': ['please include area code']
}

我想创建一个看起来像这样的字典:

new_dic = {
'urls': ['www.google.com', 'www.bing.com'],
'useremail': ['my@email.com'],
'infofield': [
              {'field': 'email'},
              {'field': 'address', 'info':'Company', 'instruction': 'Please only if the company is a LLC'},
              {'field':'phone', 'instruction': 'please include area code'}
             ]
}

重要提示:'xyzfield'是必须的,而'xyzfield_info'和'xyzfield_instruction'都是可选的。此外:用户可以添加更多字段,比如'agefield'、'agefield_info'和'agefield_instruction'。

我遇到的问题是如何高效地检查xyzfield(比如邮箱、电话等)是否在字典里。如果在的话,还要检查可选字段是否也在。这目前的做法大概是这样的:

if 'emailfield' in form_data:
    infofield = {'field': 'email'}
    if 'emailfield_info' in form_data:
         infofield['info'] = form_data['emailfield_info']
    if 'emailfield_instruction' in form_data:
         infofield['instruction'] = form_data['emailfield_instruction']

cleaned_data['infofields'].append(infofield)

...

而且我对每个字段都这样做,所以我有4到5个类似的代码。此外,我也无法处理用户自己创建的字段,因为我事先不知道它们的名字。

总之:我该如何让这个过程更高效和灵活呢?

2 个回答

1

这段话的意思是,假设你只是想清理那些实际提交的内容。如果你想要确保某些特定的东西存在,我建议你先列出一个要检查的清单,然后逐个检查这些东西是否存在。

form_data = {
    'urls': ['www.google.com', 'www.bing.com'],
    'useremail': ['my@email.com'],
    'emailfield': ['1'],
    'addressfield': ['1'],
    'addressfield_info':['Company'],
    'addressfield_instruction': ['Please only if the company is a LLC'],
    'phonefield': ['1'],
    'phonefield_instruction': ['please include area code']
}

def make_field_dict(form_data, base):
        field_dict = {}

        name_field = base + "field"
        name_info = base + "field_info"
        name_inst = base + "field_instruction"
        if name_field not in form_data:
            raise KeyError, "%s not found in form_data" % name_field
        if form_data[name_field] != ['1']:
            raise ValueError, "%s not valid in form_data" % name_field
        field_dict["field"] = base
        if name_info in form_data:
            lst = form_data[name_info]
            if len(lst) != 1:
                raise ValueError, "%s not valid in form_data" % name_info
            field_dict["info"] = lst[0]
        if name_inst in form_data:
            lst = form_data[name_inst]
            if len(lst) != 1:
                raise ValueError, "%s not valid in form_data" % name_inst
            field_dict["instruction"] = lst[0]
        return field_dict

def parse_form_data(form_data):
    cleaned_data = {}
    cleaned_data["infofield"] = []
    seen = set()
    for key, value in form_data.items():
        if "field" not in key:
            cleaned_data[key] = value
        else:
            base, _, tail = key.partition("field")
            if base in seen:
                continue
            cleaned_data["infofield"].append(make_field_dict(form_data, base))
            seen.add(base)
    return cleaned_data


new_dic = {
'urls': ['www.google.com', 'www.bing.com'],
'useremail': ['my@email.com'],
'infofield': [
              {'field': 'email'},
              {'field': 'address', 'info':'Company', 'instruction': 'Please only if the company is a LLC'},
              {'field':'phone', 'instruction': 'please include area code'}
             ]
}

clean_data = parse_form_data(form_data)

new_dic['infofield'].sort()
clean_data['infofield'].sort()
assert(new_dic == clean_data)
4

避免重复代码的标准方法在这里也适用——把重复的代码提取到一个函数里:

def extract_field(form_data, clean, fieldname, optional=('info', 'instruction')):
   if fieldname+'field' in form_data:
       infofield = { 'field': fieldname }
       for opt in optional:
           optname = '{}field_{}'.format(fieldname, opt)
           if optname in form_data:
              infofield[opt] = form_data[optname]
       clean.append(infofield)

extract_field(form_data, cleaned_data['infofields'], 'email')
extract_field(form_data, cleaned_data['infofields'], 'address')
extract_field(form_data, cleaned_data['infofields'], 'phone')

撰写回答