Python中的泛型/模板?

175 投票
10 回答
205201 浏览
提问于 2025-04-16 21:43

Python是怎么处理通用类型或者模板类型的呢?比如说,我想创建一个外部文件叫“BinaryTree.py”,让它能够处理二叉树,但不限制于某一种数据类型。

这样的话,我就可以把自定义对象的类型传给它,然后让这个二叉树存储这种对象。那在Python中是怎么做到的呢?

10 个回答

24

其实现在在Python 3.5及以上版本中,你可以使用泛型了。具体可以参考PEP-484typing模块的文档

根据我的经验,这个功能的使用并不是特别顺畅和清晰,尤其是对于那些熟悉Java泛型的人来说,不过还是可以用的。

200

其他的回答都很好:

  • 在Python中,不需要特别的语法来支持泛型。
  • 正如André所提到的,Python使用的是鸭子类型。

不过,如果你还是想要一个有类型的版本,自从Python 3.5开始就有内置的解决方案。

关于可用的类型注解的完整列表,可以在Python文档中找到。


泛型类

from typing import TypeVar, Generic, List

T = TypeVar('T')

class Stack(Generic[T]):
    def __init__(self) -> None:
        # Create an empty list with items of type T
        self.items: List[T] = []

    def push(self, item: T) -> None:
        self.items.append(item)

    def pop(self) -> T:
        return self.items.pop()

    def empty(self) -> bool:
        return not self.items
# Construct an empty Stack[int] instance
stack = Stack[int]()
stack.push(2)
stack.pop()
stack.push('x')        # Type error

泛型函数:

from typing import TypeVar, Sequence

T = TypeVar('T')      # Declare type variable

def first(seq: Sequence[T]) -> T:
    return seq[0]

def last(seq: Sequence[T]) -> T:
    return seq[-1]


n = first([1, 2, 3])  # n has type int.

静态类型检查

你需要使用一个静态类型检查器,比如mypy或者Pyre(由Meta/FB开发)来分析你的源代码。

安装mypy:

python3 -m pip install mypy

分析你的源代码,比如某个文件:

mypy foo.py

或者某个目录:

mypy some_directory

mypy会检测并打印类型错误。对于上面提供的Stack示例,具体的输出如下:

foo.py:23: error: Argument 1 to "push" of "Stack" has incompatible type "str"; expected "int"

参考资料:关于泛型运行mypy的mypy文档

116

Python使用一种叫做“鸭子类型”的方式,所以它不需要特别的语法来处理多种类型。

如果你之前用过C++,你可能还记得,只要在模板函数或类中使用的操作在某种类型T上是定义好的,你就可以在模板中使用这个类型T

所以,基本上,它的工作原理是一样的:

  1. 为你想要插入到二叉树中的项目定义一个类型的约定。
  2. 记录这个约定(比如在类的文档中)。
  3. 只用约定中指定的操作来实现二叉树。
  4. 享受这个过程。

不过你要注意,除非你写明确的类型检查(通常不推荐这样做),否则你无法强制要求二叉树只包含你选择的类型的元素。

撰写回答