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