在理解中重用表达式
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'}
是否可以在理解中重用一个可能很大、计算成本高或像生成器那样非幂等的子表达式?
假设有一个要转换为字典的字符串列表:
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'}