collections.abc.Callable 在 Python 3.9.1 中有问题吗?

Is collections.abc.Callable bugged in Python 3.9.1?

Python 3.9 includes PEP 585 and deprecates many of the types in the typing module in favor of the ones in collections.abc, now that they support __class_getitem__. This is the case with for example Callable。在我看来,typing.Callablecollections.abc.Callable 的行为应该总是相似的,但事实并非如此。

这个简单的例子导致错误:

>>> from typing import Optional
>>> from collections.abc import Callable
>>> def foo(arg: Optional[Callable[[int], int]]) -> None:
...    pass
...
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/usr/local/lib/python3.9/typing.py", line 262, in inner
    return func(*args, **kwds)
  File "/usr/local/lib/python3.9/typing.py", line 339, in __getitem__
    return self._getitem(self, parameters)
  File "/usr/local/lib/python3.9/typing.py", line 463, in Optional
    return Union[arg, type(None)]
  File "/usr/local/lib/python3.9/typing.py", line 262, in inner
    return func(*args, **kwds)
  File "/usr/local/lib/python3.9/typing.py", line 339, in __getitem__
    return self._getitem(self, parameters)
  File "/usr/local/lib/python3.9/typing.py", line 451, in Union
    parameters = _remove_dups_flatten(parameters)
  File "/usr/local/lib/python3.9/typing.py", line 231, in _remove_dups_flatten
    return tuple(_deduplicate(params))
  File "/usr/local/lib/python3.9/typing.py", line 205, in _deduplicate
    all_params = set(params)
TypeError: unhashable type: 'list'

但是 typing.Callable 不会发生同样的错误:

>>> from typing import Callable
>>> def foo(arg: Optional[Callable[[int], int]]) -> None:
...    pass
...
>>> # no error

签名稍微简化一点也不会出现这个错误:

>>> from collections.abc import Callable
>>> def foo(arg: Optional[Callable[..., int]]) -> None:
...    pass
...
>>> # no error
>>> def foo(arg: Callable[[int], int]) -> None:
...    pass
...
>>> # no error

这是 Python 3.9 和 3.9.1 中的错误吗?

是的,collections.abc.Callable 不适用于 3.9.0 和 3.9.1 中的键入目的。据报道here and is fixed in 3.9.2和3.10。在此期间您可以继续使用 typing.Callable.