在理解中重用表达式

Reusing an expression in a comprehension

是否可以在理解中重用一个可能很大、计算成本高或像生成器那样非幂等的子表达式?

假设有一个要转换为字典的字符串列表:

items = ['ab: 1', 'cd: 2', 'ef:3']  ===>  {'ab': '1', 'cd': '2', 'ef': '3'}

循环计算 "expensive" 拆分表达式一次:

d = {}
for item in items:
    k, v = item.split(':', maxsplit=1)
    d.update({k.strip(): v.strip()})

理解为每个输出元素重复计算:

d = {x.split(':', maxsplit=1)[0].strip(): x.split(':', maxsplit=1)[1].strip() for x in items}

但所需的解决方案是计算一次表达式然后重新使用它的理解:

d = {k.strip(): v.strip() for x in items for k, v in x.split(':', maxsplit=1)}     # Wrong - need an assignment

能做到吗?

a = ['ab: 1', 'cd: 2', 'ef:3']

使用带有地图和字典的生成器表达式理解

In [46]: b = (map(str.strip,thing.split(':')) for thing in a)

In [47]: d = {k:v for (k,v) in b}

In [48]: d
Out[48]: {'ab': '1', 'cd': '2', 'ef': '3'}

a中的每个项目被拆分一次,结果列表中的项目被剥离一次。这些函数的执行被延迟到字典 comprehension 被执行。

如果您不需要字典理解,dict对象已经接受了元组:

dict(map(str.strip, x.split(':')) for x in items)

# {'ab': '1', 'cd': '2', 'ef': '3'}

如果你愿意,这就是字典理解:

{k: v for k, v in [map(str.strip, x.split(':')) for x in items]}

# {'ab': '1', 'cd': '2', 'ef': '3'}