diff options
Diffstat (limited to 'Lib/collections.py')
-rw-r--r-- | Lib/collections.py | 47 |
1 files changed, 23 insertions, 24 deletions
diff --git a/Lib/collections.py b/Lib/collections.py index dba9c7d..2cf9fe8 100644 --- a/Lib/collections.py +++ b/Lib/collections.py @@ -24,30 +24,29 @@ def NamedTuple(typename, s): """ field_names = s.split() - nargs = len(field_names) - - def __new__(cls, *args, **kwds): - if kwds: - try: - args += tuple(kwds[name] for name in field_names[len(args):]) - except KeyError as name: - raise TypeError('%s missing required argument: %s' % (typename, name)) - if len(args) != nargs: - raise TypeError('%s takes exactly %d arguments (%d given)' % (typename, nargs, len(args))) - return tuple.__new__(cls, args) - - repr_template = '%s(%s)' % (typename, ', '.join('%s=%%r' % name for name in field_names)) - - m = dict(vars(tuple)) # pre-lookup superclass methods (for faster lookup) - m.update(__doc__= '%s(%s)' % (typename, ', '.join(field_names)), - __slots__ = (), # no per-instance dict (so instances are same size as tuples) - __new__ = __new__, - __repr__ = lambda self, _format=repr_template.__mod__: _format(self), - __module__ = _sys._getframe(1).f_globals['__name__'], - ) - m.update((name, property(_itemgetter(index))) for index, name in enumerate(field_names)) - - return type(typename, (tuple,), m) + if not ''.join([typename] + field_names).replace('_', '').isalnum(): + raise ValueError('Type names and field names can only contain alphanumeric characters and underscores') + argtxt = ', '.join(field_names) + reprtxt = ', '.join('%s=%%r' % name for name in field_names) + template = '''class %(typename)s(tuple): + '%(typename)s(%(argtxt)s)' + __slots__ = () + def __new__(cls, %(argtxt)s): + return tuple.__new__(cls, (%(argtxt)s,)) + def __repr__(self): + return '%(typename)s(%(reprtxt)s)' %% self + ''' % locals() + for i, name in enumerate(field_names): + template += '\n %s = property(itemgetter(%d))\n' % (name, i) + m = dict(itemgetter=_itemgetter) + exec(template, m) + result = m[typename] + if hasattr(_sys, '_getframe'): + result.__module__ = _sys._getframe(1).f_globals['__name__'] + return result + + + if __name__ == '__main__': |