Python 中泛型的实现

在学习 Python 3.10 新特性时,其中有个类型别名(TypeAlias), 所举的例子是

StrCache = 'Cache[str]' # a type alias
LOG_PREFIX = 'LOG[DEBUG]' # a module constant

可写成

StrCache: TypeAlias = 'Cache[str]' # a type alias
LOG_PREFIX = 'LOG[DEBUG]' # a module constant

这让 StrCache 更像是一个类型别名,而不是一个看起来明显就是 Cache[str] 的字符串变量(实际上它确实是)。

本文不在 TypeAlias 本身,而是从 Cache[str] 能看出 Python 似乎也能支持像 Java 那样的泛型, 就像 Python 内置支持的 List[str] 或 list[str] 那样。

那么来看 Python 怎么去实现一个只能放入字符串的  Cache[str] Cache, 而不能放入别的类型。

我们依然用到的是 Python 的 typing 模块,所以上面代码仍然是属于类 type hints 的范畴,对 Python 解释器不构成约束,只会影响到 mypy 这样的检查工具

使用上面的类

使用 python test.py 命令执行一切正常,输出为

abc
123

但在 IntelliJ IDEA 中,上面高亮的第五行 cache.put('b', 123) 行上会提示

Expected type 'str' (matched generic type 'T'), got 'int' instead

如果用 mypy 来检测

$ mypy tt.py
tt.py:13: error: Incompatible return value type (got "Optional[T]", expected "T")
tt.py:21: error: Argument 2 to "put" of "Cache" has incompatible type "int"; expected "str"
Found 2 errors in 1 file (checked 1 source file)

typing 模块中除了上面用到的 Generic, TypeVar 外,还有更多的类型约束,像 Mapping, Iterator, Sequence。还有更多的类似于 Java 的泛型功能

泛型子类型

泛型函数

更多用法,在此不一一列出。写自己的实现代码使用泛型的需要其实并不大,除非做第三方的通用库会用到泛型写法,这让别人用起来更清晰。

更多功能请参考 https://mypy.readthedocs.io/en/stable/generics.html

链接:

  1. mypy 0.961 document - Generics

 

本文链接 https://yanbin.blog/python-generic-implementation/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments