用作switch语句的python dict和list comprehension - 没有按预期工作

时间:2016-03-29 14:04:30

标签: python dictionary list-comprehension

我在使用Dict和列表理解作为案例陈述时遇到了麻烦。我只想要第一场比赛 - 但我得到了所有的比赛。这个词典很长,但看起来很明显:

categories = {  'rhsa' : 'Red Hat',
            'red hat' : 'Red Hat', 
            '.net' : 'Microsoft .Net',
            'sql server' : 'MS SQL', 
            'microsoft' : 'Microsoft',
             etc..}

功能很简单:

def vuln_category(vuln_title):
    vuln_cat = ''
    vuln_title = vuln_title.lower()
    try:
      vuln_cat = ''.join([categories[k] for k in categories if (k in vuln_title and len(vuln_cat)==0)]) # ''.join() to convert to string
       if vuln_cat == '':
            vuln_cat = 'Other'
    except KeyError:
        vuln_cat = 'Other'
return vuln_cat

我得到的是“第三方SoftwareVMWareMicrosoftVMWare”。很明显,“and len(vuln_cat)== 0”没有像我预期的那样在循环中进行评估,导致每个类别匹配连接dict值。

是的,我可以(并且已经)将它编码为嵌套循环作为一个简单的修复,但我想知道解决这个问题的正确方法。

Python版本是3.4。我试图保持这个简单,因为它是一个令人讨厌的剧本。

1 个答案:

答案 0 :(得分:2)

vuln_cat只有在列表理解完成后设置,您才能从理解中访问正在构建的列表。

使用generator expression内的next() function代替,这只会选择第一个匹配结果:

def vuln_category(vuln_title):
    vuln_title = vuln_title.lower()
    return next(
        (categories[k] for k in categories if k in vuln_title),
        'Other')

next()函数的第二个参数是默认值,如果生成器表达式没有产生任何结果,则使用该参数。

演示:

>>> categories = {
...     'rhsa': 'Red Hat',
...     'red hat': 'Red Hat',
...     '.net': 'Microsoft .Net',
...     'sql server': 'MS SQL',
...     'microsoft': 'Microsoft',
... }
>>> def vuln_category(vuln_title):
...     vuln_title = vuln_title.lower()
...     return next(
...         (categories[k] for k in categories if k in vuln_title),
...         'Other')
...
>>> vuln_category('Microsoft SQL Server on .NET')
'MS SQL'
>>> vuln_category('Red Hat RHSA')
'Red Hat'
>>> vuln_category('Mac OS X')
'Other'