I've encountered a problem when trying to define a generic (typing/mypy Generic
) NamedTuple
. I've managed to reduce it to smallest possible working example:
a.py:
from typing import NamedTuple
from typing import Generic
from typing import TypeVar
T = TypeVar('T')
class A(Generic[T], NamedTuple('A', [('x', T)])):
pass
a = A(12)
This is completely fine on all python version we (have to) support (including 3.4, 3.7), except 3.5.3, where it fails:
$ python3 a.py
Traceback (most recent call last):
File "a.py", line 10, in <module>
a = A(12)
File "/usr/lib/python3.5/typing.py", line 1126, in __new__
return _generic_new(cls.__next_in_mro__, cls, *args, **kwds)
File "/usr/lib/python3.5/typing.py", line 1087, in _generic_new
return base_cls.__new__(cls)
TypeError: __new__() missing 1 required positional argument: 'x'
I tried to manually add __new__
method:
class A(Generic[T], NamedTuple('A', [('x', T)])):
def __new__(cls, a):
return super(A, cls).__new__(cls, a)
but it fails with exactly the same error message.
Explicitly naming parameter x
(a = A(x=12)
) gives the same error message too.
Is there a way to make it work?
Please, don't tell me to upgrade python, we support multiple python versions and 3.5.3 is one of them. Upgrading python is not an option here.
CodePudding user response:
It seems the answer is pretty simple - I just reversed order of Generic
and NamedTuple
and it works in all python versions we support:
class A(NamedTuple('A', [('x', T)]), Generic[T]):
pass