我有以下(非常简化)的词典。 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。
答案 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),并且非常易读。当然,它具有稍微更精细可测试的优势,从高级逻辑中抽象出来的复杂逻辑,以及使用函数的所有其他优点。