Python Dict理解、元组与惰性评价

Python Dict理解、元组与惰性评价,python,python-3.x,dictionary,functional-programming,Python,Python 3.x,Dictionary,Functional Programming,我想看看我是否能在Python中实现一些相当懒惰的东西 我有一个dict理解,其中值是一个元组。我希望能够使用元组的第一个条目创建元组的第二个条目 举个例子应该会有所帮助 dictA = {'a': 1, 'b': 3, 'c': 42} {key: (a = someComplexFunction(value), moreComplexFunction(a)) for key, value in dictA.items()} moreComplexFunction是否可能在元组的第一个条目中

我想看看我是否能在Python中实现一些相当懒惰的东西

我有一个dict理解,其中值是一个元组。我希望能够使用元组的第一个条目创建元组的第二个条目

举个例子应该会有所帮助

dictA = {'a': 1, 'b': 3, 'c': 42}
{key: (a = someComplexFunction(value), moreComplexFunction(a)) for key, value in dictA.items()}

moreComplexFunction
是否可能在元组的第一个条目中使用计算

您可以在一个元素元组上添加第二个循环:

{key: (a, moreComplexFuntion(a)) for key, value in dictA.items() 
                                 for a in (someComplexFunction(value),)}
这使您可以访问值表达式中的
someComplexFunction(value)
的输出,但这相当难看

就我个人而言,在这种情况下,我会转向常规循环:

dictB = {}
for key, value in dictA.items():
    a = someComplexFunction(value)
    dictB[key] = (a, moreComplexFunction(a))

或者,您可以编写一个函数来返回元组:

def kv_tuple(a):
    tmp = someComplexFunction(a)
    return (a, moreComplexFunction(tmp))

{key:kv_tuple(value) for key, value in dictA.items()}
这也让您可以选择使用namedtuple之类的东西来获取元组项的名称,等等。我不知道这会快多少/慢多少。。。常规循环可能会更快(函数调用更少).

此外,使用生成器表达式和dict理解也是非常语义和惰性的:

dictA = { ... } # Your original dict

partially_computed = ((key, someComplexFunction(value))
                      for key, value in dictA.items())

dictB = {key: (a, moreComplexFunction(a)) for key, a in partially_computed}

Martijn,谢谢。这似乎是一个合理的事情想做(至少对我来说)。显然,为了清晰起见,循环更好。如果有一个聪明的语言功能,我可以利用它来实现这一点,那就太好了。:)我的+1用于常规循环。代码更简单、更高效。聪明的语言功能是“lambda函数”,它是函数式编程工具套件的一部分,可以让您嵌入该函数,即{key:(lambda x:(x,moreComplexFunction(x)))(someComplexFunction(value)),对于key,value in dictA.items()}。但它更难看,更难阅读,速度也更慢。循环很容易阅读并且可能是最快的。您可以让
someComplexFunction
实现一个,然后只需调用
moreComplexFunction(someComplexFunction(value))
,就不会影响性能。缓存中有一些开销,如果只使用一次缓存,可能会有过大的杀伤力,因此我将此作为一个注释而不是答案。这只是引入额外循环的另一种形式:-)@MartijnPieters这正是我所想的!为什么是的,是的,它是>。你知道,这就是我最终要做的,但我想要的东西是使用Python函数式编程模型的一个简洁功能。@fgnu:创建一个函数只是为了使用理解会损害效率,而且会使人困惑。只需将循环放在函数中。@eryksun-它可能会混淆,也可能更简单。对我来说,缩短语句可以让我更容易阅读(就像我说的,我更喜欢在这里命名tuple)
kv_tuple
不是一个很有描述性的名称,但我不知道它用于什么。。。可以很容易地给它一个名称,这样上面的语句就可以更清楚地从dictA中的Y数据生成X数据(以及一个更容易阅读的函数包装)。除非有充分的理由在代码的其他地方使用
kv\u tuple
,否则我同意,我可能也会使用循环。不,我绝对同意它的速度较慢。。。。只是这并不一定很难理解。我第一次评论中的斜体字暗示这将是一个一次性使用的函数。这就是为什么我建议将循环移动到显式函数中——如果目的是让代码更容易理解的话。然后,可以在表达式中调用该函数,就像使用理解一样。