为什么在表达式字段中不允许生成器中未加括号的元组?

Why are unparanthesized tuples in generators not allowed in the expression field?

# why is the following invalid
x = (k, v for k, v in some_dict.items())

# but if we wrap the expression part in parentheses it works
x = ((k, v) for k, v in some_dict.items())

我查看了文档,似乎没有找到任何相关信息?什么可能会使解析器混淆语法是不允许的?尽管有更复杂的工作:

# k, v somehow confuses the parser but this doesnt???
x = ('%s:%s:%s' % (k, v, k) for k, v in some_dict.items())

为什么我们不需要用括号包裹 %s:%s:%s % (k, v, k)

看看x = (k, v for k, v in some_dict.items()):

x = (k, v for k, v in some_dict.items())
x = ((k, v) for k, v in some_dict.items())
x = (k, (v for k, v in some_dict.items()))

需要括号来消除歧义。

x = ('%s:%s:%s' % (k, v, k) for k, v in some_dict.items()) 也需要括号:

x = ('%s:%s:%s' % k, v, k for k, v in some_dict.items())
x = ('%s:%s:%s' % k, (v, k) for k, v in some_dict.items())
x = ('%s:%s:%s' % (k, v, k) for k, v in some_dict.items())

碰巧你已经有足够的括号来解决那里的歧义,以允许它以预期的方式运行。

Python 的解析器解析这个

x =  (k, v for k, v in some_dict.items())

作为包含 k 和生成器表达式的元组:

v for k, v in some_dict.items()

但这不是一个有效的生成器表达式:它必须是,正如 PEP 289 所说:

directly inside a set of parentheses and cannot have a comma on either side

Python在这里看到的生成器不是直接在一组括号内,确实有一个逗号一方面,所以这是非法的。


之所以这样认为是因为解析器(故意)非常简单。特别是,它是一个 LL(1) 解析器,意思是:

  • 从左到右扫描标记;
  • 考虑当前标记和下一个标记(先行标记);和
  • 尽快决定表达式的含义

因此,它到达当前标记 k,并看到下一个是逗号。这是一个元组,它坚持那个决定。它只会在稍后看到 for(当当前标记为 v 时),因此它成为生成器表达式 inside 元组。解析器不会回溯以查看是否存在潜在的合法表达式解析(存在 - 你想要的元组位于生成器表达式内,但可能并不总是存在),它只是立即抛出错误。