什么是“软关键词”?

根据 keyword模块的文档,Python 3.9中添加了两个新成员:

  • issoftkeyword
  • softkwlist

然而,他们的文档并没有透露他们的任何目的。在 最新消息文章中甚至没有提到这个变化,通常所有的 API 变化都有文档记录。进一步挖掘到 源代码最终导致这个 撤回请求,在那里提到了 “这本质上是一个内部工具”“软关键字仍未使用”。那么 Python 的软关键字的目的是什么呢?

9773 次浏览

Short: Soft keywords can still be used as variable or argument names.

PEP 622 sheds some light (Emphasis mine):

The difference between hard and soft keywords is that hard keywords are always reserved words, even in positions where they make no sense (e.g. x = class + 1), while soft keywords only get a special meaning in context.

[...] The match and case keywords are proposed to be soft keywords, so that they are recognized as keywords at the beginning of a match statement or case block respectively, but are allowed to be used in other places as variable or argument names.

Soft keywords are keywords that are context sensitive. For example, it'd allow you to use class as a variable name as long as it can't be interpreted as defining a class. It'd allow use to replace cls with class for example.

Today that's not possible, since class is a keyword:

>>> def a(class):
File "<stdin>", line 1
def a(class):
^

Given the context it's clear that the user didn't intend to define a new class, but wanted an identifier named class.

I think this is best explained with a demo. async and await were soft keywords in Python 3.5 and 3.6, and thus they could be used as identifiers:

>>> async = "spam"
>>> async def foo():
...     pass
...
>>> await = "bar"
>>> async, await
('spam', 'bar')

But in Python 3.7 they became proper keywords and can only be used in specific contexts where they make sense:

>>> 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

The idea in first introducing them as soft keywords was mainly to not break any existing code that uses them as identifiers. The same reasoning is with the upcoming match keyword which would completely break for example re.match and millions of projects.