According to the docs, "built-in generic types .. are valid both as types and as base classes." It gives an example deriving from Dict[str, List[Node]]
.
However, when I try this with Tuple[int, int]
, the constructor doesn't forward properly. For example:
from typing import Tuple
class MyTuple(Tuple[int, int]):
def hello(self):
print("hello: " + str(len(self)))
MyTuple([1, 2]).hello()
prints hello: 0
. If I derive from the builtin tuple
instead, it prints hello: 2
.
How can I initialize the base tuple
object when deriving from Tuple[int, int]
?
Types in the typing
module are not really meant to be directly instantiated: they're supposed to be used as static type hints in annotations.
But if you really need to, you can override __new__()
to return a tuple:
class MyTuple(Tuple[int, int]):
def __new__(cls, *args, **kwargs):
return tuple(*args, **kwargs)
print(MyTuple('abc')) # -> ('a', 'b', 'c')
This will create plain tuple objects every time you call MyTuple()
. If instead you want the objects to be instances of your class:
class MyTuple(Tuple[int, int]):
def __new__(cls, *args, **kwargs):
return tuple.__new__(cls, *args, **kwargs)
print(MyTuple('abc')) # -> ('a', 'b', 'c')
print(type(MyTuple('abc'))) # -> __main__.MyTuple
This works because typing.Tuple
is a subclass of tuple
.
Note that calling super().__new__()
would not work, because typing.Tuple
(and other generic types) discard the arguments that you pass to them. You have to "short-circuit" by calling tuple.__new__()
directly.