【发布时间】:2020-06-04 21:41:43
【问题描述】:
是否可以在推导式中重用可能很大、计算成本高或非幂等的子表达式(如生成器)?
假设有一个要转换为字典的字符串列表:
items = ['ab: 1', 'cd: 2', 'ef:3'] ===> {'ab': '1', 'cd': '2', 'ef': '3'}
循环计算一次“昂贵”的拆分表达式:
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
可以吗?
【问题讨论】:
-
在这种情况下你有
d = {k.strip(): v.strip() for x in items for k, v in [x.split(':')]},但我认为这并不能一概而论。你看过python.org/dev/peps/pep-0572吗? -
问题不在于它不能泛化,问题在于它不起作用。这是一个语法正确的理解,但它循环分割输出而不是分配它。
-
如果你有多个元素,你就无法摆脱循环。您的玩具示例中昂贵的操作是拆分,它只发生一次(
items中的每个元素当然是必要的)。此外,for k, v in [x.split(':')]只有一个循环迭代。它采用单元素列表[['ab', '1']]并使用元组解包将其映射到k和v -
PEP 572 正是我们所需要的——我正在运行 Python 3.7,但将安装 3.8 来尝试它。可惜实现了这么长时间,似乎即使在 Python 2 中对赋值表达式的需求也是显而易见的。这是 40 年前的 C 语言。
标签: python dictionary-comprehension