为什么 mypy 不承认 Mapping.get() 的参数只是位置参数?

Why does mypy not recognize that arguments to Mapping.get() are positional only?

方法Mapping.get没有关键字参数,它们只是位置参数。如果误用,为什么 mypy 检测不到?

$ mypy --command "a: str = dict(b='yes').get('a', default='no')"
Success: no issues found in 1 source file
$ python
Python 3.9.1 (default, Jan 13 2021, 15:21:08) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> a: str = dict(b='yes').get('a', default='no')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: dict.get() takes no keyword arguments

2016 年有一个 PR,其中引入了约定,即以两个下划线开头的参数仅适用于 mypy。这样的基本类型根本就没有遵循这个约定吗?我想知道为什么。

请注意,PEP 570 已创建 2018 年刚刚引入 Python 3.8。

很多内置函数不带关键字参数,看这个bug report,2010年开的,主要原因有

  • 开销: 内置函数是在 C 中实现的,解析位置参数或关键字参数会带来一些计算开销(尽管这似乎有所缓解 in the meantime
  • 很少的附加值: 通常,内置函数的函数签名相当小,所以没有 kwargs 没什么大不了的
  • 无需求:很多内置的都比较老,存在时间长,w/o这是过去的问题,这是历史证据开发者没有要求拥有 kwargs
  • 很多努力:位置参数可以很容易地重命名,它们的范围仅限于函数本身的实现,而不是调用者; kwargs 有点成为语言的一部分,需要经过深思熟虑,因为它们以后不容易更改

因此,mypy应该报错,但实际上并没有。由于内置存根是在 typeshed 中键入的,因此有一个 open bug report in the typeshed issue tracker at github.