[Python-checkins] r55448 - in python/trunk: Doc/lib/libcollections.tex Lib/collections.py Lib/test/test_collections.py

raymond.hettinger python-checkins at python.org
Sat May 19 03:11:22 CEST 2007


Author: raymond.hettinger
Date: Sat May 19 03:11:16 2007
New Revision: 55448

Modified:
   python/trunk/Doc/lib/libcollections.tex
   python/trunk/Lib/collections.py
   python/trunk/Lib/test/test_collections.py
Log:
Improvements to NamedTuple's implementation, tests, and documentation

Modified: python/trunk/Doc/lib/libcollections.tex
==============================================================================
--- python/trunk/Doc/lib/libcollections.tex	(original)
+++ python/trunk/Doc/lib/libcollections.tex	Sat May 19 03:11:16 2007
@@ -378,14 +378,25 @@
   The use cases are the same as those for tuples.  The named factories
   assign meaning to each tuple position and allow for more readable,
   self-documenting code.  Named tuples can also be used to assign field names 
-  to tuples
-  returned by the \module{csv} or \module{sqlite3} modules.  For example:
+  to tuples returned by the \module{csv} or \module{sqlite3} modules.
+  For example:
 
   \begin{verbatim}
+from itertools import starmap
 import csv
 EmployeeRecord = NamedTuple('EmployeeRecord', 'name age title department paygrade')
-for tup in csv.reader(open("employees.csv", "rb")):
-    print EmployeeRecord(*tup)
+for record in starmap(EmployeeRecord, csv.reader(open("employees.csv", "rb"))):
+    print record
+\end{verbatim}
+
+  To cast an individual record stored as \class{list}, \class{tuple}, or some other
+  iterable type, use the star-operator to unpack the values:
+
+  \begin{verbatim}
+>>> Color = NamedTuple('Color', 'name code')
+>>> m = dict(red=1, green=2, blue=3)
+>>> print Color(*m.popitem())
+Color(name='blue', code=3)
 \end{verbatim}
 
 \end{funcdesc}

Modified: python/trunk/Lib/collections.py
==============================================================================
--- python/trunk/Lib/collections.py	(original)
+++ python/trunk/Lib/collections.py	Sat May 19 03:11:16 2007
@@ -24,30 +24,29 @@
     """
 
     field_names = s.split()
-    nargs = len(field_names)
+    assert ''.join(field_names).replace('_', '').isalpha()      # protect against exec attacks
+    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 += '\t%s = property(itemgetter(%d))\n' % (name, i)
+    m = dict(itemgetter=_itemgetter)
+    exec template in m
+    result = m[typename]
+    if hasattr(_sys, '_getframe'):
+        result.__module__ = _sys._getframe(1).f_globals['__name__']
+    return result
+
+
 
-    def __new__(cls, *args, **kwds):
-        if kwds:
-            try:
-                args += tuple(kwds[name] for name in field_names[len(args):])
-            except KeyError, 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 __name__ == '__main__':

Modified: python/trunk/Lib/test/test_collections.py
==============================================================================
--- python/trunk/Lib/test/test_collections.py	(original)
+++ python/trunk/Lib/test/test_collections.py	Sat May 19 03:11:16 2007
@@ -11,7 +11,6 @@
         self.assertEqual(Point.__slots__, ())
         self.assertEqual(Point.__module__, __name__)
         self.assertEqual(Point.__getitem__, tuple.__getitem__)
-        self.assert_('__getitem__' in Point.__dict__)                       # superclass methods localized
 
     def test_instance(self):
         Point = NamedTuple('Point', 'x y')
@@ -50,8 +49,10 @@
 
 
 def test_main(verbose=None):
+    import collections as CollectionsModule
     test_classes = [TestNamedTuple]
     test_support.run_unittest(*test_classes)
+    test_support.run_doctest(CollectionsModule, verbose)
 
 if __name__ == "__main__":
     test_main(verbose=True)


More information about the Python-checkins mailing list