如何在继承typing.Tuple时初始化基础tuple对象?
解决继承
Tuple[int, int]时的初始化问题 这个问题的核心在于:typing.Tuple本质上是设计用来做类型提示的工具,虽然PEP 484提到它可以用作基类,但它的内部实现并没有像内置tuple那样处理子类的实例化逻辑,导致参数没有正确转发到底层的tuple对象。
方案1:重写__new__方法(兼容旧Python版本)
因为tuple是不可变类型,实例创建依赖__new__方法而不是__init__。我们需要手动把参数转发给父类的__new__,确保底层tuple被正确初始化:
from typing import Tuple class MyTuple(Tuple[int, int]): def __new__(cls, *args, **kwargs): # 把所有参数转发给父类的__new__方法 return super().__new__(cls, *args, **kwargs) def hello(self): print("hello: " + str(len(self))) # 两种调用方式都能正常工作 MyTuple(1, 2).hello() # 输出: hello: 2 MyTuple([1, 2]).hello() # 输出: hello: 2
方案2:使用PEP 585内置泛型(推荐Python 3.9+)
从Python 3.9开始,内置的tuple、list等类型已经支持泛型注解,不需要再用typing.Tuple来做基类。这种方式更直观,也能避免旧typing模块的坑:
from typing import Generic, TypeVar # 定义类型变量,用于约束元组的元素类型 T = TypeVar('T') U = TypeVar('U') class MyTuple(tuple[T, U], Generic[T, U]): def hello(self): print("hello: " + str(len(self))) # 同样支持两种调用方式 MyTuple(1, 2).hello() # 输出: hello: 2 MyTuple([1, 2]).hello() # 输出: hello: 2
为什么原来的代码会输出hello: 0?
当你直接继承typing.Tuple[int, int]且不重写__new__时,子类的构造逻辑并没有正确把传入的可迭代对象[1,2]传递给底层的tuple构造函数,导致创建了一个空的tuple实例,所以len(self)返回0。而继承内置tuple时,Python会自动处理参数转发,所以能正确初始化。
内容的提问来源于stack exchange,提问作者Martin C. Martin
相关产品推荐
相关产品推荐

