Named Tuples

As with tuples, named tuple classes require some special behaviors for typechecking.

Defining Named Tuples

A named tuple class can be defined using a class syntax or a factory functioncall.

Type checkers should support the class syntax:

classPoint(NamedTuple):x:inty:intunits:str="meters"

Fields must be annotated attributes - methods and un-annotated attributes are notconsidered fields. Field names may not start with an underscore:

classMyTuple(NamedTuple):x1=1# Not a fielddefx2()->None:pass# Not a field_x3:int# Type error: illegal field name

Regardless of whether the class syntax or factory function call is used to definea named tuple, type checkers should synthesize a__new__ method based onthe named tuple fields. This mirrors the runtime behavior. In the exampleabove, the synthesized__new__ method would look like the following:

def__new__(cls,x:int,y:int,units:str="meters")->Self:...

The runtime implementation ofNamedTuple enforces that fields with defaultvalues must come after fields without default values. Type checkers shouldlikewise enforce this restriction:

classLocation(NamedTuple):altitude:float=0.0latitude:float# Type error (previous field has a default value)longitude:float

A named tuple class can be subclassed, but any fields added by the subclassare not considered part of the named tuple type. Type checkers should enforcethat these newly-added fields do not conflict with the named tuple fieldsin the base class:

classPointWithName(Point):name:str# OKx:int# Type error (invalid override of named tuple field)

In Python 3.11 and newer, the class syntax supports generic named tuple classes.Type checkers should support this:

classProperty[T](NamedTuple):name:strvalue:Treveal_type(Property("height",3.4))# Revealed type is Property[float]

NamedTuple does not support multiple inheritance. Type checkers shouldenforce this limitation:

classUnit(NamedTuple,object):# Type errorname:str

The factory function call supports two variants:collections.namedtuple andtyping.NamedTuple. The latter provides a way to specify the typesof the fields in the tuple whereas the former does not. Thenamedtupleform allows fields to be specified as a tuple or list of strings or a singlestring with fields separated by whitespace or commas. TheNamedTuplefunctional form accepts an iterable of(name,type) pairs.For thenamedtuple form, all fields are assumed to be of typeAny.

A type checker may support the factory function call in its various forms:

Point1=namedtuple('Point1',['x','y'])Point2=namedtuple('Point2',('x','y'))Point3=namedtuple('Point3','x y')Point4=namedtuple('Point4','x, y')Point5=NamedTuple('Point5',[('x',int),('y',int)])Point6=NamedTuple('Point6',(('x',int),('y',int)))

At runtime, thenamedtuple function disallows field names that begin withan underscore or are illegal Python identifiers, and either raises an exceptionor replaces these fields with a parameter name of the form_N. The behaviordepends on the value of therename argument. Type checkers may replicatethis behavior statically:

NT1=namedtuple("NT1",["a","a"])# Type error (duplicate field name)NT2=namedtuple("NT2",["abc","def"],rename=False)# Type error (illegal field name)NT3=namedtuple("NT3",["abc","_d"],rename=False)# Type error (illegal field name)NT4=namedtuple("NT4",["abc","def"],rename=True)# OKNT4(abc="",_1="")# OKNT5=namedtuple("NT5",["abc","_d"],rename=True)# OKNT5(abc="",_1="")# OK

Thenamedtuple function also supports adefaults keyword argument thatspecifies default values for the fields. Type checkers may support this:

NT4=namedtuple("NT4","a b c",defaults=(1,2))NT4()# Type error (too few arguments)NT4(1)# OK

Named Tuple Usage

The fields within a named tuple instance can be accessed by name using anattribute access (.) operator. Type checkers should support this:

p=Point(1,2)assert_type(p.x,int)assert_type(p.units,str)

Like normal tuples, elements of a named tuple can also be accessed by index,and type checkers should support this:

assert_type(p[0],int)assert_type(p[2],str)

Type checkers should enforce that named tuple fields cannot be overwrittenor deleted:

p.x=3# Type errorp[0]=3# Type errordelp.x# Type errordelp[0]# Type error

Like regular tuples, named tuples can be unpacked. Type checkers should understandthis:

x,y,units=passert_type(x,int)assert_type(units,str)x,y=p# Type error (too few values to unpack)

Assignability

A named tuple isassignable to atuple with a known length andparameterized by types corresponding to the named tuple’s individual fieldtypes:

p=Point(x=1,y=2,units="inches")v1:tuple[int,int,str]=p# OKv2:tuple[Any,...]=p# OKv3:tuple[int,int]=p# Type error (too few elements)v4:tuple[int,str,str]=p# Type error (incompatible element type)

As with normal tuples, named tuples are covariant in their type parameters:

v5:tuple[float,float,str]=p# OK