mirror of
https://github.com/python/cpython.git
synced 2025-11-25 04:34:37 +00:00
More docs, error messages, and tests
This commit is contained in:
parent
050afbf214
commit
abfd8dff3b
3 changed files with 21 additions and 9 deletions
|
|
@ -365,9 +365,13 @@ they add the ability to access fields by name instead of position index.
|
|||
|
||||
The *fieldnames* are a single string with each fieldname separated by whitespace
|
||||
and/or commas (for example 'x y' or 'x, y'). Alternatively, the *fieldnames*
|
||||
can be specified as a list of strings (such as ['x', 'y']). Any valid
|
||||
Python identifier may be used for a fieldname except for names starting and
|
||||
ending with double underscores.
|
||||
can be specified as a list of strings (such as ['x', 'y']).
|
||||
|
||||
Any valid Python identifier may be used for a fieldname except for names
|
||||
starting and ending with double underscores. Valid identifiers consist of
|
||||
letters, digits, and underscores but do not start with a digit and cannot be
|
||||
a :mod:`keyword` such as *class*, *for*, *return*, *global*, *pass*, *print*,
|
||||
or *raise*.
|
||||
|
||||
If *verbose* is true, will print the class definition.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ __all__ = ['deque', 'defaultdict', 'named_tuple']
|
|||
|
||||
from _collections import deque, defaultdict
|
||||
from operator import itemgetter as _itemgetter
|
||||
from keyword import iskeyword as _iskeyword
|
||||
import sys as _sys
|
||||
|
||||
def named_tuple(typename, field_names, verbose=False):
|
||||
|
|
@ -35,6 +36,8 @@ def named_tuple(typename, field_names, verbose=False):
|
|||
for name in (typename,) + field_names:
|
||||
if not name.replace('_', '').isalnum():
|
||||
raise ValueError('Type names and field names can only contain alphanumeric characters and underscores: %r' % name)
|
||||
if _iskeyword(name):
|
||||
raise ValueError('Type names and field names cannot be a keyword: %r' % name)
|
||||
if name[0].isdigit():
|
||||
raise ValueError('Type names and field names cannot start with a number: %r' % name)
|
||||
seen_names = set()
|
||||
|
|
|
|||
|
|
@ -11,11 +11,17 @@ class TestNamedTuple(unittest.TestCase):
|
|||
self.assertEqual(Point.__slots__, ())
|
||||
self.assertEqual(Point.__module__, __name__)
|
||||
self.assertEqual(Point.__getitem__, tuple.__getitem__)
|
||||
self.assertRaises(ValueError, named_tuple, 'abc%', 'def ghi')
|
||||
self.assertRaises(ValueError, named_tuple, 'abc', 'def g%hi')
|
||||
self.assertRaises(ValueError, named_tuple, 'abc', '__def__ ghi')
|
||||
self.assertRaises(ValueError, named_tuple, 'abc', 'def def ghi')
|
||||
self.assertRaises(ValueError, named_tuple, 'abc', '8def 9ghi')
|
||||
|
||||
self.assertRaises(ValueError, named_tuple, 'abc%', 'efg ghi') # type has non-alpha char
|
||||
self.assertRaises(ValueError, named_tuple, 'class', 'efg ghi') # type has keyword
|
||||
self.assertRaises(ValueError, named_tuple, '9abc', 'efg ghi') # type starts with digit
|
||||
|
||||
self.assertRaises(ValueError, named_tuple, 'abc', 'efg g%hi') # field with non-alpha char
|
||||
self.assertRaises(ValueError, named_tuple, 'abc', 'abc class') # field has keyword
|
||||
self.assertRaises(ValueError, named_tuple, 'abc', '8efg 9ghi') # field starts with digit
|
||||
self.assertRaises(ValueError, named_tuple, 'abc', '__efg__ ghi') # field with double underscores
|
||||
self.assertRaises(ValueError, named_tuple, 'abc', 'efg efg ghi') # duplicate field
|
||||
|
||||
named_tuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
|
||||
|
||||
def test_instance(self):
|
||||
|
|
@ -66,7 +72,6 @@ class TestNamedTuple(unittest.TestCase):
|
|||
self.assertEqual(p.y, y)
|
||||
self.assertRaises(AttributeError, eval, 'p.z', locals())
|
||||
|
||||
|
||||
def test_odd_sizes(self):
|
||||
Zero = named_tuple('Zero', '')
|
||||
self.assertEqual(Zero(), ())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue