在Python dict中重用函数结果

时间:2017-08-08 12:41:08

标签: python python-2.7

我有以下(非常简化)的词典。 get_details函数是一个API调用,我希望避免两次。

ret = { 
    'a': a,
    'b': [{
        'c': item.c,
        'e': item.get_details()[0].e,
        'h': [func_h(detail) for detail in item.get_details()],
    } for item in items]
}

我当然可以像这样重写代码:

b = []
for item in items:
    details = item.get_details()
    b.append({
        'c': item.c,
        'e': details[0].e,
        'h': [func_h(detail) for detail in details],
    })

ret = { 
    'a': a,
    'b': b
}

但是我想使用第一种方法,因为它似乎更像pythonic。

3 个答案:

答案 0 :(得分:6)

您可以使用中间生成器从项目中提取详细信息。像这样:

ret = { 
    'a': a,
    'b': [{
        'c': item.c,
        'e': details[0].e,
        'h': [func_h(detail) for detail in details],
    } for (item, details) in ((item, item.get_details()) for item in items)]
}

答案 1 :(得分:3)

我没有发现第二个特别是非pythonic;你有一个复杂的初始化,你不应该期望归结为一个简单的表达式。也就是说,您不需要临时列表b;您可以直接使用ret['b']

ret = { 
    'a': a,
    'b': []
}

for item in items:
    details = item.get_details()
    d = details[0]
    ret['b'].append({
        'c': item.c,
        'e': d.e,
        'h': map(func_h, details)
    })

这也是我在列表理解上选择map的情况。 (如果这是Python 3,则需要在对list的额外调用中包装它。)

答案 2 :(得分:-1)

如果它看起来像你的第一种方法,我不会太努力变得更加pythonic。我会将你的第二种方法更进一步,只需使用一个单独的函数:

ret = {
    'a': a,
    'b': get_b_from_items(items)
}

我认为它尽可能干净。使用注释/文档字符串来指示'b'是什么,测试函数,然后下一个出现的人可以快速阅读并信任您的代码。我知道你知道如何编写这个函数,但为了完整起见,我会怎么做:

# and add this in where you want it
def get_b_from_items(items):
    """Return a list of (your description here)."""
    result = []
    for item in items:
        details = item.get_details()
        result.append({
            'c': item.c,
            'e': details[0].e,
            'h': [func_h(detail) for detail in details],
        })
    return result

这是很多pythonic(请注意docstring--非常pythonic),并且非常易读。当然,它具有稍微更精细可测试的优势,从高级逻辑中抽象出来的复杂逻辑,以及使用函数的所有其他优点。