为什么 Python `f-string` + 内联 for 循环在作为参数传递时创建生成器?

Why does Python `f-string` + inline for loop create a generator when they're passed as parameter?

我在网上找到这个例子

def format_attributes(**attributes):
    """Return a string of comma-separated key-value pairs."""
    return ", ".join(
        f"{param}: {value}"
        for param, value in attributes.items()
    )

传递给 join 函数的参数的语法引起了我的注意,因为它有点不寻常。但它有效

使用最少的代码库进行一些本地测试我发现:

def foo(res):
    return res

print(foo(f"{s}" for s in ["bar"]))

foo's 语法有效,res 最终成为生成器。但是,如果我尝试 f"{s}" for s in ["bar"] 独立(中间没有函数),表达式只会抛出 SyntaxError: invalid syntax.

为什么 f-string + for loop 有效并被转换为 generator?调用 foo 函数时发生了什么?

这些其他问题使用相同的语法:

但我没有找到解释为什么会发生这种情况的评论

这些是生成器表达式的示例,不一定有任何特定于 f 字符串的内容或与它们一起使用的函数。

例如

>>> x = [1, 2, 3, 4]
>>> sum(i%2==0 for i in x)
2

示例计算列表中偶数的个数。

您可以在这里阅读更多关于它们的信息:https://dbader.org/blog/python-generator-expressions

f弦与它无关。

尽管生成器表达式通常需要括号:

some_gen = (f"{s}" for s in ["bar"])
print(foo(some_gen))

当生成器表达式只是函数调用的参数时,括号可以省略:

# These two calls are equivalent.
foo((f"{s}" for s in ["bar"]))
foo( f"{s}" for s in ["bar"] )

您使用的循环结构是 generator expression。要写一个独立的表达式,你需要在它两边加上括号:

genexp = (f"{s}" for s in ["bar"])

如果生成器表达式是函数的唯一参数,则不需要双括号(但如果有其他单独的参数则需要)。对比度:

s = sum(i % 2 for i in some_sequence) # count of odd elements, no extra parentheses needed

对比:

print(*(i for i in some_sequence if i % 2), sep=",") # print odds, parens are needed this time

您代码中的生成器表达式中使用的 f 字符串没有什么特别之处,任何表达式的工作方式都相同。