Eliminate camelcase function name

This commit is contained in:
Raymond Hettinger 2007-10-08 21:26:58 +00:00
parent 814b04600c
commit a48a29947a
4 changed files with 50 additions and 36 deletions

View File

@ -12,7 +12,7 @@
This module implements high-performance container datatypes. Currently, This module implements high-performance container datatypes. Currently,
there are two datatypes, :class:`deque` and :class:`defaultdict`, and there are two datatypes, :class:`deque` and :class:`defaultdict`, and
one datatype factory function, :func:`NamedTuple`. Python already one datatype factory function, :func:`named_tuple`. Python already
includes built-in containers, :class:`dict`, :class:`list`, includes built-in containers, :class:`dict`, :class:`list`,
:class:`set`, and :class:`tuple`. In addition, the optional :mod:`bsddb` :class:`set`, and :class:`tuple`. In addition, the optional :mod:`bsddb`
module has a :meth:`bsddb.btopen` method that can be used to create in-memory module has a :meth:`bsddb.btopen` method that can be used to create in-memory
@ -25,7 +25,7 @@ ordered dictionaries.
Added :class:`defaultdict`. Added :class:`defaultdict`.
.. versionchanged:: 2.6 .. versionchanged:: 2.6
Added :class:`NamedTuple`. Added :func:`named_tuple`.
.. _deque-objects: .. _deque-objects:
@ -348,14 +348,14 @@ Setting the :attr:`default_factory` to :class:`set` makes the
.. _named-tuple-factory: .. _named-tuple-factory:
:func:`NamedTuple` Factory Function for Tuples with Named Fields :func:`named_tuple` Factory Function for Tuples with Named Fields
---------------------------------------------------------------- -----------------------------------------------------------------
Named tuples assign meaning to each position in a tuple and allow for more readable, Named tuples assign meaning to each position in a tuple and allow for more readable,
self-documenting code. They can be used wherever regular tuples are used, and self-documenting code. They can be used wherever regular tuples are used, and
they add the ability to access fields by name instead of position index. they add the ability to access fields by name instead of position index.
.. function:: NamedTuple(typename, fieldnames, [verbose]) .. function:: named_tuple(typename, fieldnames, [verbose])
Returns a new tuple subclass named *typename*. The new subclass is used to 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 create tuple-like objects that have fields accessable by attribute lookup as
@ -363,22 +363,22 @@ they add the ability to access fields by name instead of position index.
helpful docstring (with typename and fieldnames) and a helpful :meth:`__repr__` helpful docstring (with typename and fieldnames) and a helpful :meth:`__repr__`
method which lists the tuple contents in a ``name=value`` format. method which lists the tuple contents in a ``name=value`` format.
The *fieldnames* are a single string with each fieldname separated by a space The *fieldnames* are a single string with each fieldname separated by whitespace
and/or comma (for example "x y" or "x, y"). Alternately, the *fieldnames* and/or commas (for example 'x y' or 'x, y'). Alternatively, the *fieldnames*
can be specified as list or tuple of strings. Any valid Python identifier can be specified as a list of strings (such as ['x', 'y']). Any valid
may be used for a fieldname except for names starting and ending with double Python identifier may be used for a fieldname except for names starting and
underscores. ending with double underscores.
If *verbose* is true, will print the class definition. If *verbose* is true, will print the class definition.
*NamedTuple* instances do not have per-instance dictionaries, so they are Named tuple instances do not have per-instance dictionaries, so they are
lightweight and require no more memory than regular tuples. lightweight and require no more memory than regular tuples.
.. versionadded:: 2.6 .. versionadded:: 2.6
Example:: Example::
>>> Point = NamedTuple('Point', 'x y', verbose=True) >>> Point = named_tuple('Point', 'x y', verbose=True)
class Point(tuple): class Point(tuple):
'Point(x, y)' 'Point(x, y)'
__slots__ = () __slots__ = ()
@ -410,27 +410,35 @@ Example::
Named tuples are especially useful for assigning field names to result tuples returned Named tuples are especially useful for assigning field names to result tuples returned
by the :mod:`csv` or :mod:`sqlite3` modules:: by the :mod:`csv` or :mod:`sqlite3` modules::
EmployeeRecord = named_tuple('EmployeeRecord', 'name, age, title, department, paygrade')
from itertools import starmap from itertools import starmap
import csv import csv
EmployeeRecord = NamedTuple('EmployeeRecord', 'name age title department paygrade')
for emp in starmap(EmployeeRecord, csv.reader(open("employees.csv", "rb"))): for emp in starmap(EmployeeRecord, csv.reader(open("employees.csv", "rb"))):
print emp.name, emp.title print emp.name, emp.title
When casting a single record to a *NamedTuple*, use the star-operator [#]_ to unpack import sqlite3
conn = sqlite3.connect('/companydata')
cursor = conn.cursor()
cursor.execute('SELECT name, age, title, department, paygrade FROM employees')
for emp in starmap(EmployeeRecord, cursor.fetchall()):
print emp.name, emp.title
When casting a single record to a named tuple, use the star-operator [#]_ to unpack
the values:: the values::
>>> t = [11, 22] >>> t = [11, 22]
>>> Point(*t) # the star-operator unpacks any iterable object >>> Point(*t) # the star-operator unpacks any iterable object
Point(x=11, y=22) Point(x=11, y=22)
When casting a dictionary to a *NamedTuple*, use the double-star-operator:: When casting a dictionary to a named tuple, use the double-star-operator::
>>> d = {'x': 11, 'y': 22} >>> d = {'x': 11, 'y': 22}
>>> Point(**d) >>> Point(**d)
Point(x=11, y=22) Point(x=11, y=22)
In addition to the methods inherited from tuples, named tuples support In addition to the methods inherited from tuples, named tuples support
additonal methods and a read-only attribute. two additonal methods and a read-only attribute.
.. method:: somenamedtuple.__asdict__() .. method:: somenamedtuple.__asdict__()
@ -464,8 +472,8 @@ additonal methods and a read-only attribute.
>>> p.__fields__ # view the field names >>> p.__fields__ # view the field names
('x', 'y') ('x', 'y')
>>> Color = NamedTuple('Color', 'red green blue') >>> Color = named_tuple('Color', 'red green blue')
>>> Pixel = NamedTuple('Pixel', Point.__fields__ + Color.__fields__) >>> Pixel = named_tuple('Pixel', Point.__fields__ + Color.__fields__)
>>> Pixel(11, 22, 128, 255, 0) >>> Pixel(11, 22, 128, 255, 0)
Pixel(x=11, y=22, red=128, green=255, blue=0)' Pixel(x=11, y=22, red=128, green=255, blue=0)'

View File

@ -1,13 +1,13 @@
__all__ = ['deque', 'defaultdict', 'NamedTuple'] __all__ = ['deque', 'defaultdict', 'named_tuple']
from _collections import deque, defaultdict from _collections import deque, defaultdict
from operator import itemgetter as _itemgetter from operator import itemgetter as _itemgetter
import sys as _sys import sys as _sys
def NamedTuple(typename, field_names, verbose=False): def named_tuple(typename, field_names, verbose=False):
"""Returns a new subclass of tuple with named fields. """Returns a new subclass of tuple with named fields.
>>> Point = NamedTuple('Point', 'x y') >>> Point = named_tuple('Point', 'x y')
>>> Point.__doc__ # docstring for the new class >>> Point.__doc__ # docstring for the new class
'Point(x, y)' 'Point(x, y)'
>>> p = Point(11, y=22) # instantiate with positional args or keywords >>> p = Point(11, y=22) # instantiate with positional args or keywords
@ -36,6 +36,10 @@ def NamedTuple(typename, field_names, verbose=False):
raise ValueError('Type names and field names can only contain alphanumeric characters and underscores') raise ValueError('Type names and field names can only contain alphanumeric characters and underscores')
if any(name.startswith('__') and name.endswith('__') for name in field_names): if any(name.startswith('__') and name.endswith('__') for name in field_names):
raise ValueError('Field names cannot start and end with double underscores') raise ValueError('Field names cannot start and end with double underscores')
if any(name[:1].isdigit() for name in field_names):
raise ValueError('Field names cannot start with a number')
if len(field_names) != len(set(field_names)):
raise ValueError('Encountered duplicate field name')
# Create and fill-in the class template # Create and fill-in the class template
argtxt = repr(field_names).replace("'", "")[1:-1] # tuple repr without parens or quotes argtxt = repr(field_names).replace("'", "")[1:-1] # tuple repr without parens or quotes
@ -83,10 +87,10 @@ def NamedTuple(typename, field_names, verbose=False):
if __name__ == '__main__': if __name__ == '__main__':
# verify that instances can be pickled # verify that instances can be pickled
from cPickle import loads, dumps from cPickle import loads, dumps
Point = NamedTuple('Point', 'x, y', True) Point = named_tuple('Point', 'x, y', True)
p = Point(x=10, y=20) p = Point(x=10, y=20)
assert p == loads(dumps(p)) assert p == loads(dumps(p))
import doctest import doctest
TestResults = NamedTuple('TestResults', 'failed attempted') TestResults = named_tuple('TestResults', 'failed attempted')
print TestResults(*doctest.testmod()) print TestResults(*doctest.testmod())

View File

@ -1,23 +1,25 @@
import unittest import unittest
from test import test_support from test import test_support
from collections import NamedTuple from collections import named_tuple
class TestNamedTuple(unittest.TestCase): class TestNamedTuple(unittest.TestCase):
def test_factory(self): def test_factory(self):
Point = NamedTuple('Point', 'x y') Point = named_tuple('Point', 'x y')
self.assertEqual(Point.__name__, 'Point') self.assertEqual(Point.__name__, 'Point')
self.assertEqual(Point.__doc__, 'Point(x, y)') self.assertEqual(Point.__doc__, 'Point(x, y)')
self.assertEqual(Point.__slots__, ()) self.assertEqual(Point.__slots__, ())
self.assertEqual(Point.__module__, __name__) self.assertEqual(Point.__module__, __name__)
self.assertEqual(Point.__getitem__, tuple.__getitem__) self.assertEqual(Point.__getitem__, tuple.__getitem__)
self.assertRaises(ValueError, NamedTuple, 'abc%', 'def ghi') self.assertRaises(ValueError, named_tuple, 'abc%', 'def ghi')
self.assertRaises(ValueError, NamedTuple, 'abc', 'def g%hi') self.assertRaises(ValueError, named_tuple, 'abc', 'def g%hi')
self.assertRaises(ValueError, NamedTuple, 'abc', '__def__ ghi') self.assertRaises(ValueError, named_tuple, 'abc', '__def__ ghi')
NamedTuple('Point0', 'x1 y2') # Verify that numbers are allowed in names self.assertRaises(ValueError, named_tuple, 'abc', 'def def ghi')
self.assertRaises(ValueError, named_tuple, 'abc', '8def 9ghi')
named_tuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
def test_instance(self): def test_instance(self):
Point = NamedTuple('Point', 'x y') Point = named_tuple('Point', 'x y')
p = Point(11, 22) p = Point(11, 22)
self.assertEqual(p, Point(x=11, y=22)) self.assertEqual(p, Point(x=11, y=22))
self.assertEqual(p, Point(11, y=22)) self.assertEqual(p, Point(11, y=22))
@ -36,17 +38,17 @@ class TestNamedTuple(unittest.TestCase):
self.assertEqual(p.__asdict__(), dict(x=11, y=22)) # test __dict__ method self.assertEqual(p.__asdict__(), dict(x=11, y=22)) # test __dict__ method
# verify that field string can have commas # verify that field string can have commas
Point = NamedTuple('Point', 'x, y') Point = named_tuple('Point', 'x, y')
p = Point(x=11, y=22) p = Point(x=11, y=22)
self.assertEqual(repr(p), 'Point(x=11, y=22)') self.assertEqual(repr(p), 'Point(x=11, y=22)')
# verify that fieldspec can be a non-string sequence # verify that fieldspec can be a non-string sequence
Point = NamedTuple('Point', ('x', 'y')) Point = named_tuple('Point', ('x', 'y'))
p = Point(x=11, y=22) p = Point(x=11, y=22)
self.assertEqual(repr(p), 'Point(x=11, y=22)') self.assertEqual(repr(p), 'Point(x=11, y=22)')
def test_tupleness(self): def test_tupleness(self):
Point = NamedTuple('Point', 'x y') Point = named_tuple('Point', 'x y')
p = Point(11, 22) p = Point(11, 22)
self.assert_(isinstance(p, tuple)) self.assert_(isinstance(p, tuple))
@ -66,9 +68,9 @@ class TestNamedTuple(unittest.TestCase):
def test_odd_sizes(self): def test_odd_sizes(self):
Zero = NamedTuple('Zero', '') Zero = named_tuple('Zero', '')
self.assertEqual(Zero(), ()) self.assertEqual(Zero(), ())
Dot = NamedTuple('Dot', 'd') Dot = named_tuple('Dot', 'd')
self.assertEqual(Dot(1), (1,)) self.assertEqual(Dot(1), (1,))
def test_main(verbose=None): def test_main(verbose=None):

View File

@ -544,7 +544,7 @@ Library
- Added heapq.merge() for merging sorted input streams. - Added heapq.merge() for merging sorted input streams.
- Added collections.NamedTuple() for assigning field names to tuples. - Added collections.named_tuple() for assigning field names to tuples.
- Added itertools.izip_longest(). - Added itertools.izip_longest().