Python 3.9包含PEP 585并弃用了typing
模块中的许多类型,转而collections.abc
支持__class_getitem__
. 例如 就是这种情况Callable
。对我来说,这似乎typing.Callable
并且collections.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 中的错误吗?