You do not want a different class definition. You merely want to make those arguments optional with a default value for the attribute if you didn't pass in a month
value. The namedtuple()
factory function doesn't support that use-case.
But that's no the only way to create a named tuple. You can also subclass typing.NamedTuple
:
from typing import NamedTuple, Optional
class VagueTimePeriod(NamedTuple):
year: int
month: Optional[int] = None
That's a class definition for a named tuple where month
is optional, if you don't specify a month it is left to the default value:
>>> VagueTimePeriod(2012)
VagueTimePeriod(year=2012, month=None)
>>> VagueTimePeriod(2012, 3)
VagueTimePeriod(year=2012, month=3)
However, I suspect that what you really want is a dataclass. A simple class that mostly just holds some data.
Python 3.7 has the new dataclasses
module, or you can install the attrs
project. A dataclass can have optional attributes (defaulting to a value you state at definition time):
from dataclasses import dataclass
from typing import Optional
@dataclass
class VagueTimePeriod:
year: int
month: Optional[int] = None
vtp1 = VagueTimePeriod(2012)
vtp2 = VagueTimePeriod(2012, 3)
Dataclasses give you greatly simplified syntax to define a small class, which comes with a representation, equality testing, and optional ordering support, hashing, and immutability.
Dataclasses also fully support inheritance, which named tuples don't.
A dataclass is not automatically iterable or immutable, but can be made so, see this previous answer of mine, where I define a simple DataclassSequence
base class that adds sequence behaviour.
A quick demo:
>>> @dataclass(frozen=True)
... class VagueTimePeriod:
... year: int
... month: Optional[int] = None
...
>>> VagueTimePeriod(2012)
VagueTimePeriod(year=2012, month=None)
VagueTimePeriod(2012, 3)
VagueTimePeriod(year=2012, month=3)