blob: 8e9f6d676c66ac2fece0d76bf777c96c659cb4cd [file] [log] [blame]
Guido van Rossumd8faa362007-04-27 19:54:29 +00001__all__ = ['deque', 'defaultdict', 'NamedTuple']
2
3from _collections import deque, defaultdict
4from operator import itemgetter as _itemgetter
5import sys as _sys
6
Guido van Rossumcd16bf62007-06-13 18:07:49 +00007# For bootstrapping reasons, the collection ABCs are defined in _abcoll.py.
8# They should however be considered an integral part of collections.py.
9from _abcoll import *
10import _abcoll
11__all__ += _abcoll.__all__
12
13
Guido van Rossumd8faa362007-04-27 19:54:29 +000014def NamedTuple(typename, s):
15 """Returns a new subclass of tuple with named fields.
16
17 >>> Point = NamedTuple('Point', 'x y')
18 >>> Point.__doc__ # docstring for the new class
19 'Point(x, y)'
20 >>> p = Point(11, y=22) # instantiate with positional args or keywords
21 >>> p[0] + p[1] # works just like the tuple (11, 22)
22 33
23 >>> x, y = p # unpacks just like a tuple
24 >>> x, y
25 (11, 22)
26 >>> p.x + p.y # fields also accessable by name
27 33
28 >>> p # readable __repr__ with name=value style
29 Point(x=11, y=22)
30
31 """
32
33 field_names = s.split()
Guido van Rossumd59da4b2007-05-22 18:11:13 +000034 if not ''.join([typename] + field_names).replace('_', '').isalnum():
35 raise ValueError('Type names and field names can only contain alphanumeric characters and underscores')
36 argtxt = ', '.join(field_names)
37 reprtxt = ', '.join('%s=%%r' % name for name in field_names)
38 template = '''class %(typename)s(tuple):
39 '%(typename)s(%(argtxt)s)'
40 __slots__ = ()
41 def __new__(cls, %(argtxt)s):
42 return tuple.__new__(cls, (%(argtxt)s,))
43 def __repr__(self):
44 return '%(typename)s(%(reprtxt)s)' %% self
45 ''' % locals()
46 for i, name in enumerate(field_names):
47 template += '\n %s = property(itemgetter(%d))\n' % (name, i)
48 m = dict(itemgetter=_itemgetter)
49 exec(template, m)
50 result = m[typename]
51 if hasattr(_sys, '_getframe'):
52 result.__module__ = _sys._getframe(1).f_globals['__name__']
53 return result
Guido van Rossumd8faa362007-04-27 19:54:29 +000054
Guido van Rossumd8faa362007-04-27 19:54:29 +000055
Guido van Rossumd8faa362007-04-27 19:54:29 +000056
Guido van Rossumd8faa362007-04-27 19:54:29 +000057
58
59if __name__ == '__main__':
60 # verify that instances are pickable
Guido van Rossum99603b02007-07-20 00:22:32 +000061 from pickle import loads, dumps
Guido van Rossumd8faa362007-04-27 19:54:29 +000062 Point = NamedTuple('Point', 'x y')
63 p = Point(x=10, y=20)
64 assert p == loads(dumps(p))
65
66 import doctest
67 TestResults = NamedTuple('TestResults', 'failed attempted')
68 print(TestResults(*doctest.testmod()))