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