什么是“软关键词”?
根据keyword模块的文档,Python 3.9 中添加了两个新成员:
issoftkeywordsoftkwlist
然而,他们的文档并未透露任何有关其目的的信息。新功能文章中甚至没有提到此更改,通常所有 API 更改都记录在文档中。深入挖掘源代码最终会导致这个拉取请求,其中提到“这本质上是一个内部工具”和“软关键字仍未使用”。那么 Python 的 soft 关键字的目的是什么?
回答
简短:软关键字仍然可以用作变量或参数名称。
PEP 622 说明了一些问题(重点是我的):
硬关键字和软关键字的区别在于硬关键字始终是保留字,即使在它们没有意义的位置(例如 x = class + 1),而软关键字仅在上下文中具有特殊含义。
[...] match 和 case 关键字被建议为软关键字,以便它们分别在 match 语句或 case 块的开头被识别为关键字,但允许在其他地方用作变量或参数名称.
- PEP 634 contains the same example (`match` and `case`) but does not provide a general explanation of what a soft keyword is. PEP 622 does.
- @chepner See [this issue from 2003](https://bugs.python.org/issue691733), which was actually by myself — assigning to `None` was definitely a `SyntaxWarning` in 2003, and assigning to `as` was too up to and including Python 2.5.
- Or even [PEP 634](https://www.python.org/dev/peps/pep-0634/) which superseded 622
- In Python 2, `True` and `False` weren't keywords at all: they were *just* identifiers in the built-in scope. Neither `as` nor `None` have even been valid identifier names. (At least, I *think* `as` has been a keyword from the beginning, as part of the `import` statement. If it was ever a valid identifier, it was sometime prior to Python 1.5.)
- also called [contextual keywords](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/contextual-keywords) in C++ and C#, and [Context-sensitive keywords](https://docs.microsoft.com/en-us/cpp/extensions/context-sensitive-keywords-cpp-component-extensions?view=msvc-160) in C++/CLI
回答
我认为最好通过演示来解释这一点。asyncandawait是 Python 3.5 和 3.6 中的软关键字,因此它们可以用作标识符:
>>> async = "spam"
>>> async def foo():
... pass
...
>>> await = "bar"
>>> async, await
('spam', 'bar')
但是在 Python 3.7 中,它们变成了正确的关键字,并且只能在有意义的特定上下文中使用:
>>> async = "123"
File "<stdin>", line 1
async = "123"
^
SyntaxError: invalid syntax
>>> async def foo():
... pass
...
>>> await = "bar"
File "<stdin>", line 1
await = "bar"
^
SyntaxError: invalid syntax
>>> async, await
File "<stdin>", line 1
async, await
^
SyntaxError: invalid syntax
首先将它们作为软关键字引入的想法主要是为了不破坏任何使用它们作为标识符的现有代码。同样的推理是即将到来的match关键字,它会完全破坏例如re.match和数百万个项目。
回答
软关键字是上下文敏感的关键字。例如,class只要它不能被解释为定义类,它就允许您用作变量名。它会允许使用,以取代cls用class的例子。
今天这是不可能的,因为class是一个关键字:
>>> def a(class):
File "<stdin>", line 1
def a(class):
^
鉴于上下文,很明显用户不打算定义一个新类,而是想要一个名为 的标识符class。
- More importantly, it works in the other direction, too: it let's you *add* a keyword to the language without invalidating its use as a variable name in existing code. One reason why the assignment operator `:=` exists is because no suitable re-use of an existing keyword (`as`) could be agreed on. My personal preferance would have been `let x = 3 in x * 2` as opposed to `(x:=3) + 2`, but an extremely high bar is set for adding keywords because of the risk of breaking existing code.