将 str.join 与 python 中的生成器表达式一起使用

Use str.join with generator expression in python

当我阅读问题Python string.join(list) on object array rather than string array时,我发现了以下句子:

', '.join(str(x) for x in list)

我已经知道 (str(x) for x in list) 是一个生成器表达式,我也知道生成器是一个可迭代的。下面的代码验证了我的观点的正确性。

>>> gen = (x for x in [1,2,3])
<generator object <genexpr> at 0x104349b40>
>>> from collections import Iterable
>>> isinstance(gen, Iterable)
True

同时,str.join(iterable) return一个字符串,是iterable中字符串的拼接。所以下面的工作正常,如我所愿。

>>> ",".join((str(x) for x in [1,2,3]))
'123'

那么问题来了,为什么代码在下面也能正常工作,为什么在函数调用中不需要括号。

', '.join(str(x) for x in [1,2,3])

毕竟str(x) for x in [1,2,3]本身不是发电机

>>> tmp = str(x) for x in [1,2,3]
  File "<stdin>", line 1
    tmp = str(x) for x in [1,2,3]
                   ^
SyntaxError: invalid syntax

这是在引入生成器表达式时指定的 (PEP 289):

if a function call has a single positional argument, it can be a generator expression without extra parentheses, but in all other cases you have to parenthesize it.

在你的例子中,它是一个单一的位置参数,所以两种方式都是可能的:

', '.join(str(x) for x in [1,2,3])
', '.join((str(x) for x in [1,2,3]))

逐字逐句仔细阅读文档,发现提到了Generator expressions:

The parentheses can be omitted on calls with only one argument. See section Calls for the detail.

无论哪种方式,它都是一个生成器表达式 - 但是是否需要括起来的括号取决于生成器表达式出现的上下文。参数列表是一种特殊情况:如果生成器表达式是唯一的参数,则不需要括起来的括号(但如果您愿意,仍然可以使用)。但是,如果一个调用有多个参数,则需要用括号括起来。这本质上是点 2B in the PEP that introduced this feature.