Returns a new subclass of tuple with named fields. >>> Point = namedtuple('Point', ['x', 'y']) >>> Point.__doc__ # docstring for the new class 'Point(x, y)' >>> p = Point(11, y=22) # instantiate with positional args or keywords >>> p[0] + p[1]
(typename, field_names, *, rename=False, defaults=None, module=None)
| 348 | _tuplegetter = lambda index, doc: property(_itemgetter(index), doc=doc) |
| 349 | |
| 350 | def namedtuple(typename, field_names, *, rename=False, defaults=None, module=None): |
| 351 | """Returns a new subclass of tuple with named fields. |
| 352 | |
| 353 | >>> Point = namedtuple('Point', ['x', 'y']) |
| 354 | >>> Point.__doc__ # docstring for the new class |
| 355 | 'Point(x, y)' |
| 356 | >>> p = Point(11, y=22) # instantiate with positional args or keywords |
| 357 | >>> p[0] + p[1] # indexable like a plain tuple |
| 358 | 33 |
| 359 | >>> x, y = p # unpack like a regular tuple |
| 360 | >>> x, y |
| 361 | (11, 22) |
| 362 | >>> p.x + p.y # fields also accessible by name |
| 363 | 33 |
| 364 | >>> d = p._asdict() # convert to a dictionary |
| 365 | >>> d['x'] |
| 366 | 11 |
| 367 | >>> Point(**d) # convert from a dictionary |
| 368 | Point(x=11, y=22) |
| 369 | >>> p._replace(x=100) # _replace() is like str.replace() but targets named fields |
| 370 | Point(x=100, y=22) |
| 371 | |
| 372 | """ |
| 373 | |
| 374 | # Validate the field names. At the user's option, either generate an error |
| 375 | # message or automatically replace the field name with a valid name. |
| 376 | if isinstance(field_names, str): |
| 377 | field_names = field_names.replace(',', ' ').split() |
| 378 | field_names = list(map(str, field_names)) |
| 379 | typename = _sys.intern(str(typename)) |
| 380 | |
| 381 | if rename: |
| 382 | seen = set() |
| 383 | for index, name in enumerate(field_names): |
| 384 | if (not name.isidentifier() |
| 385 | or _iskeyword(name) |
| 386 | or name.startswith('_') |
| 387 | or name in seen): |
| 388 | field_names[index] = f'_{index}' |
| 389 | seen.add(name) |
| 390 | |
| 391 | for name in [typename] + field_names: |
| 392 | if type(name) is not str: |
| 393 | raise TypeError('Type names and field names must be strings') |
| 394 | if not name.isidentifier(): |
| 395 | raise ValueError('Type names and field names must be valid ' |
| 396 | f'identifiers: {name!r}') |
| 397 | if _iskeyword(name): |
| 398 | raise ValueError('Type names and field names cannot be a ' |
| 399 | f'keyword: {name!r}') |
| 400 | |
| 401 | seen = set() |
| 402 | for name in field_names: |
| 403 | if name.startswith('_') and not rename: |
| 404 | raise ValueError('Field names cannot start with an underscore: ' |
| 405 | f'{name!r}') |
| 406 | if name in seen: |
| 407 | raise ValueError(f'Encountered duplicate field name: {name!r}') |