Python中的泛型/模板?
Python是怎么处理通用类型或者模板类型的呢?比如说,我想创建一个外部文件叫“BinaryTree.py”,让它能够处理二叉树,但不限制于某一种数据类型。
这样的话,我就可以把自定义对象的类型传给它,然后让这个二叉树存储这种对象。那在Python中是怎么做到的呢?
10 个回答
24
其实现在在Python 3.5及以上版本中,你可以使用泛型了。具体可以参考PEP-484和typing模块的文档。
根据我的经验,这个功能的使用并不是特别顺畅和清晰,尤其是对于那些熟悉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"
116
Python使用一种叫做“鸭子类型”的方式,所以它不需要特别的语法来处理多种类型。
如果你之前用过C++,你可能还记得,只要在模板函数或类中使用的操作在某种类型T
上是定义好的,你就可以在模板中使用这个类型T
。
所以,基本上,它的工作原理是一样的:
- 为你想要插入到二叉树中的项目定义一个类型的约定。
- 记录这个约定(比如在类的文档中)。
- 只用约定中指定的操作来实现二叉树。
- 享受这个过程。
不过你要注意,除非你写明确的类型检查(通常不推荐这样做),否则你无法强制要求二叉树只包含你选择的类型的元素。