[Python-checkins] r58186 - in python/trunk: Doc/library/collections.rst Lib/collections.py Lib/test/test_collections.py

raymond.hettinger python-checkins at python.org
Tue Sep 18 05:33:19 CEST 2007


Author: raymond.hettinger
Date: Tue Sep 18 05:33:19 2007
New Revision: 58186

Modified:
   python/trunk/Doc/library/collections.rst
   python/trunk/Lib/collections.py
   python/trunk/Lib/test/test_collections.py
Log:
Handle corner cased on 0-tuples and 1-tuples.  Add verbose option so people can see how it works.

Modified: python/trunk/Doc/library/collections.rst
==============================================================================
--- python/trunk/Doc/library/collections.rst	(original)
+++ python/trunk/Doc/library/collections.rst	Tue Sep 18 05:33:19 2007
@@ -364,7 +364,7 @@
 --------------------------------------------
 
 
-.. function:: NamedTuple(typename, fieldnames)
+.. function:: NamedTuple(typename, fieldnames, [verbose])
 
    Returns a new tuple subclass named *typename*.  The new subclass is used to
    create tuple-like objects that have fields accessable by attribute lookup as
@@ -412,6 +412,23 @@
       >>> print Color(*m.popitem())
       Color(name='blue', code=3)
 
+   If *verbose* is true, the *NamedTuple* call will print the class definition::
+
+       >>> Point = NamedTuple('Point', 'x y', verbose=True)
+       class Point(tuple):
+               'Point(x, y)'
+               __slots__ = ()
+               __fields__ = ('x', 'y')
+               def __new__(cls, x, y):
+                   return tuple.__new__(cls, (x, y))
+               def __repr__(self):
+                   return 'Point(x=%r, y=%r)' % self
+               def __replace__(self, field, value):
+                   'Return a new Point object replacing one field with a new value'
+                   return Point(**dict(zip(('x', 'y'), self) + [(field, value)]))
+               x = property(itemgetter(0))
+               y = property(itemgetter(1))
+
 In addition to the methods inherited from tuples, named tuples support
 an additonal method and an informational read-only attribute.
 

Modified: python/trunk/Lib/collections.py
==============================================================================
--- python/trunk/Lib/collections.py	(original)
+++ python/trunk/Lib/collections.py	Tue Sep 18 05:33:19 2007
@@ -4,7 +4,7 @@
 from operator import itemgetter as _itemgetter
 import sys as _sys
 
-def NamedTuple(typename, s):
+def NamedTuple(typename, s, verbose=False):
     """Returns a new subclass of tuple with named fields.
 
     >>> Point = NamedTuple('Point', 'x y')
@@ -28,25 +28,26 @@
 
     """
 
-    field_names = tuple(s.replace(',', ' ').split())   # names separated by spaces and/or commas
+    field_names = tuple(s.replace(',', ' ').split())    # names separated by spaces and/or commas
     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)
+    argtxt = repr(field_names).replace("'", "")[1:-1]   # tuple repr without parens or quotes
     reprtxt = ', '.join('%s=%%r' % name for name in field_names)
     template = '''class %(typename)s(tuple):
         '%(typename)s(%(argtxt)s)'
         __slots__ = ()
         __fields__ = %(field_names)r
         def __new__(cls, %(argtxt)s):
-            return tuple.__new__(cls, (%(argtxt)s,))
+            return tuple.__new__(cls, (%(argtxt)s))
         def __repr__(self):
             return '%(typename)s(%(reprtxt)s)' %% self
         def __replace__(self, field, value):
             'Return a new %(typename)s object replacing one field with a new value'
-            return %(typename)s(**dict(zip(%(field_names)r, self) + [(field, value)]))
-    ''' % locals()
+            return %(typename)s(**dict(zip(%(field_names)r, self) + [(field, value)]))  \n''' % locals()
     for i, name in enumerate(field_names):
-        template += '\n        %s = property(itemgetter(%d))\n' % (name, i)
+        template += '        %s = property(itemgetter(%d))\n' % (name, i)
+    if verbose:
+        print template
     m = dict(itemgetter=_itemgetter)
     exec template in m
     result = m[typename]
@@ -62,7 +63,7 @@
 if __name__ == '__main__':
     # verify that instances can be pickled
     from cPickle import loads, dumps
-    Point = NamedTuple('Point', 'x, y')
+    Point = NamedTuple('Point', 'x, y', True)
     p = Point(x=10, y=20)
     assert p == loads(dumps(p))
 

Modified: python/trunk/Lib/test/test_collections.py
==============================================================================
--- python/trunk/Lib/test/test_collections.py	(original)
+++ python/trunk/Lib/test/test_collections.py	Tue Sep 18 05:33:19 2007
@@ -58,6 +58,12 @@
         self.assertRaises(AttributeError, eval, 'p.z', locals())
 
 
+    def test_odd_sizes(self):
+        Zero = NamedTuple('Zero', '')
+        self.assertEqual(Zero(), ())
+        Dot = NamedTuple('Dot', 'd')
+        self.assertEqual(Dot(1), (1,))
+
 def test_main(verbose=None):
     import collections as CollectionsModule
     test_classes = [TestNamedTuple]


More information about the Python-checkins mailing list