为什么在 Python 3.8 之前,在 return 语句中加星标的可迭代解包是不带括号的无效语法?
Why is starred iterable unpacking in a return statement invalid syntax without parentheses before Python 3.8?
Python 语言(尤其是 3.x)允许对迭代对象进行非常普遍的解包,一个简单的例子是
a, *rest = 1, 2, 3
多年来,这种解包已逐渐推广(参见 PEP 3132 and PEP 448),使其可以在越来越多的情况下使用。因此,我惊讶地发现以下是 Python 3.6 中的无效语法(并且在 Python 3.7 中仍然如此):
def f():
rest = [2, 3]
return 1, *rest # Invalid
我可以通过将 returned 元组封装在括号中来使其工作,如下所示:
def f():
rest = [2, 3]
return (1, *rest) # Valid
我在 return
语句中使用它这一事实似乎很重要,因为
t = 1, *rest
确实是合法的,无论有没有括号,结果都是一样的。
这种情况是否只是被 Python 开发人员遗忘了,或者这种情况是无效语法的任何原因?
为什么我关心
这打破了我认为我与 Python 语言的重要约定。考虑以下(也是有效的)解决方案:
def f():
rest = [2, 3]
t = 1, *rest
return t
通常当我有这样的代码时,我认为 t
是一个临时名称,我应该能够摆脱它,只需将底行中的 t
替换为它的定义。但是在这种情况下,这会导致无效代码
def f():
rest = [2, 3]
return 1, *rest
在return值两边加括号当然没什么大不了的,但通常额外加括号只是为了区分几种可能的结果(分组)。此处情况并非如此,因为省略括号不会产生其他一些不需要的行为,而是根本不会产生任何行为。
更新
从 Python 3.8 开始(参见 this list 上的第 7 项),上面讨论的通用语法现在有效。
根据 this commit 对 Python 3.2.
的评论,我怀疑这是一个意外
该提交使赋值表达式能够采用 testlist_star_expr
产生式(允许未加括号的解包),但使 return 语句采用 testlist
产生式。我怀疑提交只是错过了这个(可能还有其他位置,但我现在专注于 return_stmt
生产)。
我继续修改 Python Grammar/Grammar 文件以允许这样做。所有测试都继续通过,包括 test_grammar.py
文件中的测试(但这似乎并不十分详尽)。
如果你好奇,this is the change I made. Feel free to clone or download my fork。
更新: 我已经提交了 bpo issue and a pull request 用于 return(和收益)解包。
Python 语言(尤其是 3.x)允许对迭代对象进行非常普遍的解包,一个简单的例子是
a, *rest = 1, 2, 3
多年来,这种解包已逐渐推广(参见 PEP 3132 and PEP 448),使其可以在越来越多的情况下使用。因此,我惊讶地发现以下是 Python 3.6 中的无效语法(并且在 Python 3.7 中仍然如此):
def f():
rest = [2, 3]
return 1, *rest # Invalid
我可以通过将 returned 元组封装在括号中来使其工作,如下所示:
def f():
rest = [2, 3]
return (1, *rest) # Valid
我在 return
语句中使用它这一事实似乎很重要,因为
t = 1, *rest
确实是合法的,无论有没有括号,结果都是一样的。
这种情况是否只是被 Python 开发人员遗忘了,或者这种情况是无效语法的任何原因?
为什么我关心
这打破了我认为我与 Python 语言的重要约定。考虑以下(也是有效的)解决方案:
def f():
rest = [2, 3]
t = 1, *rest
return t
通常当我有这样的代码时,我认为 t
是一个临时名称,我应该能够摆脱它,只需将底行中的 t
替换为它的定义。但是在这种情况下,这会导致无效代码
def f():
rest = [2, 3]
return 1, *rest
在return值两边加括号当然没什么大不了的,但通常额外加括号只是为了区分几种可能的结果(分组)。此处情况并非如此,因为省略括号不会产生其他一些不需要的行为,而是根本不会产生任何行为。
更新
从 Python 3.8 开始(参见 this list 上的第 7 项),上面讨论的通用语法现在有效。
根据 this commit 对 Python 3.2.
的评论,我怀疑这是一个意外该提交使赋值表达式能够采用 testlist_star_expr
产生式(允许未加括号的解包),但使 return 语句采用 testlist
产生式。我怀疑提交只是错过了这个(可能还有其他位置,但我现在专注于 return_stmt
生产)。
我继续修改 Python Grammar/Grammar 文件以允许这样做。所有测试都继续通过,包括 test_grammar.py
文件中的测试(但这似乎并不十分详尽)。
如果你好奇,this is the change I made. Feel free to clone or download my fork。
更新: 我已经提交了 bpo issue and a pull request 用于 return(和收益)解包。