我读过很多关于泛型类的内容,虽然这些很酷,但有时,我只需要一个泛型函数。这是我写的一篇小文章:
def _matrix_map(self, mapper):
"""returns the matrix applying the mapper funcfunc"""
return {key: mapper(value) for key, value in self._matrix.items()}
这应该如何为类型进行注释。在具有通用支持的静态类型语言中,我会这样写
private Dictionary<KeyType, ValueType> matrix;
private Dictionary<KeyType, T> matrix_map<T>(Func<ValueType, T>)
所以,我想我应该这样写:
T = TypeVar('T')
def _matrix_map(self, mapper: Callable[[Tile], T]) -> Dict[Coordinate, T]:
我像这样通过 mypy 传递了它,但 pylint 讨厌这个。
第一行:
C0103:Invalid class attribute name "T"
第二行:
E0602:Undefined variable 'T'
所以我觉得我做错了什么,我可以更改变量名称(
ttt
?typ
?),但这并不能解决第二个问题。我不是第一个想要(静态类型)泛型函数的人,但我在任何地方都找不到任何好的资源。有什么推荐吗?
我猜你写的代码大致是这样的?
class Matrix:
T = TypeVar('T')
def _matrix_map(self, mapper: Callable[[Tile], T]) -> Dict[Coordinate, T]:
# ...snip...
实际上在运行时没有问题/mypy 没有问题,但 pylint 似乎对您将“T”放在类定义的范围内不满意。为了满足 pylint 的要求,你可以这样做:
T = TypeVar('T')
class Matrix:
def _matrix_map(self, mapper: Callable[[Tile], T]) -> Dict[Coordinate, T]:
# ...snip...
这与前面的代码片段完全相同,并且也满足 pylint。
(顺便说一句,我认为 pylint 对前者不满意的事实实际上是一个错误。但公平地说,目前还没有任何关于类型提示最佳实践的既定风格指南/放置嵌套作用域内的 typevar 是一个不太常见的用例,所以我想我不能真的责怪他们没有考虑到这种情况。)
唯一的缺点是,将 TypeVar 放在外部确实看起来有点不整洁/似乎会污染全局名称空间。您可以通过将其重命名为类似
_T
之类的名称来部分缓解此问题,以表明它是私有的。每当您需要另一个泛型类或函数时,您也可以重用此类型变量,这也有望有助于减少命名空间污染。
有关使用带有 Python 类型提示的泛型的更多信息,请参阅 http://mypy.readthedocs.io/en/stable/generics.html
随着 Python 3.12 中引入 类型参数列表,不再需要显式定义
TypeVar
。 (另请注意,typing.Dict
在 Python 3.9 中已弃用,因为可以使用 dict
本身来代替。)
from collections.abc import Callable
class Matrix:
def _matrix_map[T](self, mapper: Callable[[Tile], T]) -> dict[Coordinate, T]:
...
如果类型参数要被所有方法共享,也可以在类级别声明。
class Matrix[T]:
def _matrix_map(self, mapper: Callable[[Tile], T]) -> dict[Coordinate, T]:
...