Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
c37e5e04
Commit
c37e5e04
authored
Mar 01, 2007
by
Raymond Hettinger
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add collections.NamedTuple
parent
eb979889
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
170 additions
and
3 deletions
+170
-3
Doc/lib/libcollections.tex
Doc/lib/libcollections.tex
+51
-2
Lib/collections.py
Lib/collections.py
+60
-1
Lib/test/test_collections.py
Lib/test/test_collections.py
+57
-0
Misc/NEWS
Misc/NEWS
+2
-0
No files found.
Doc/lib/libcollections.tex
View file @
c37e5e04
...
...
@@ -9,14 +9,16 @@
This module implements high-performance container datatypes. Currently,
there are two datatypes, deque and defaultdict.
there are two datatypes, deque and defaultdict, and one datatype factory
function,
\function
{
NamedTuple
}
.
Future additions may include balanced trees and ordered dictionaries.
\versionchanged
[Added defaultdict]
{
2.5
}
\versionchanged
[Added NamedTuple]
{
2.6
}
\subsection
{
\class
{
deque
}
objects
\label
{
deque-objects
}}
\begin{funcdesc}
{
deque
}{
\optional
{
iterable
}}
Returns a new deque object
ed
initialized left-to-right (using
Returns a new deque object initialized left-to-right (using
\method
{
append()
}
) with data from
\var
{
iterable
}
. If
\var
{
iterable
}
is not specified, the new deque is empty.
...
...
@@ -339,3 +341,50 @@ Setting the \member{default_factory} to \class{set} makes the
>>> d.items()
[('blue', set([2, 4])), ('red', set([1, 3]))]
\end{verbatim}
\subsection
{
\function
{
NamedTuple
}
datatype factory function
\label
{
named-tuple-factory
}}
\begin{funcdesc}
{
NamedTuple
}{
typename, fieldnames
}
Returns a new tuple subclass named
\var
{
typename
}
. The new subclass is used
to create tuple-like objects that have fields accessable by attribute
lookup as well as being indexable and iterable. Instances of the subclass
also have a helpful docstring (with typename and fieldnames) and a helpful
\method
{__
repr
__
()
}
method which lists the tuple contents in a
\code
{
name=value
}
format.
\versionadded
{
2.6
}
The
\var
{
fieldnames
}
are specified in a single string and are separated by spaces.
Any valid Python identifier may be used for a field name.
Example:
\begin{verbatim}
>>> Point = NamedTuple('Point', 'x y')
>>> Point.
__
doc
__
# docstring for the new datatype
'Point(x, y)'
>>> p = Point(11, y=22) # instantiate with positional or keyword arguments
>>> p[0] + p[1] # works just like the tuple (11, 22)
33
>>> x, y = p # unpacks just like a tuple
>>> x, y
(11, 22)
>>> p.x + p.y # fields also accessable by name
33
>>> p # readable
__
repr
__
with name=value style
Point(x=11, y=22)
\end{verbatim}
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. Can also be used to assign field names to tuples
returned by the
\module
{
csv
}
or
\module
{
sqlite3
}
modules. For example:
\begin{verbatim}
import csv
EmployeeRecord = NamedTuple('EmployeeRecord', 'name age title deparment paygrade')
for tup in csv.reader(open("employees.csv", "rb")):
print EmployeeRecord(*tup)
\end{verbatim}
\end{funcdesc}
Lib/collections.py
View file @
c37e5e04
__all__
=
[
'deque'
,
'defaultdict'
]
__all__
=
[
'deque'
,
'defaultdict'
,
'NamedTuple'
]
from
_collections
import
deque
,
defaultdict
from
operator
import
itemgetter
as
_itemgetter
import
sys
as
_sys
def
NamedTuple
(
typename
,
s
):
"""Returns a new subclass of tuple with named fields.
>>> Point = NamedTuple('Point', 'x y')
>>> Point.__doc__ # docstring for the new class
'Point(x, y)'
>>> p = Point(11, y=22) # instantiate with positional args or keywords
>>> p[0] + p[1] # works just like the tuple (11, 22)
33
>>> x, y = p # unpacks just like a tuple
>>> x, y
(11, 22)
>>> p.x + p.y # fields also accessable by name
33
>>> p # readable __repr__ with name=value style
Point(x=11, y=22)
"""
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
,
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__'
:
# verify that instances are pickable
from
cPickle
import
loads
,
dumps
Point
=
NamedTuple
(
'Point'
,
'x y'
)
p
=
Point
(
x
=
10
,
y
=
20
)
assert
p
==
loads
(
dumps
(
p
))
import
doctest
TestResults
=
NamedTuple
(
'TestResults'
,
'failed attempted'
)
print
TestResults
(
*
doctest
.
testmod
())
Lib/test/test_collections.py
0 → 100644
View file @
c37e5e04
import
unittest
from
test
import
test_support
from
collections
import
NamedTuple
class
TestNamedTuple
(
unittest
.
TestCase
):
def
test_factory
(
self
):
Point
=
NamedTuple
(
'Point'
,
'x y'
)
self
.
assertEqual
(
Point
.
__name__
,
'Point'
)
self
.
assertEqual
(
Point
.
__doc__
,
'Point(x, y)'
)
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'
)
p
=
Point
(
11
,
22
)
self
.
assertEqual
(
p
,
Point
(
x
=
11
,
y
=
22
))
self
.
assertEqual
(
p
,
Point
(
11
,
y
=
22
))
self
.
assertEqual
(
p
,
Point
(
y
=
22
,
x
=
11
))
self
.
assertEqual
(
p
,
Point
(
*
(
11
,
22
)))
self
.
assertEqual
(
p
,
Point
(
**
dict
(
x
=
11
,
y
=
22
)))
self
.
assertRaises
(
TypeError
,
Point
,
1
)
# too few args
self
.
assertRaises
(
TypeError
,
Point
,
1
,
2
,
3
)
# too many args
self
.
assertRaises
(
TypeError
,
eval
,
'Point(XXX=1, y=2)'
,
locals
())
# wrong keyword argument
self
.
assertRaises
(
TypeError
,
eval
,
'Point(x=1)'
,
locals
())
# missing keyword argument
self
.
assertEqual
(
repr
(
p
),
'Point(x=11, y=22)'
)
self
.
assert_
(
'__dict__'
not
in
dir
(
p
))
# verify instance has no dict
self
.
assert_
(
'__weakref__'
not
in
dir
(
p
))
def
test_tupleness
(
self
):
Point
=
NamedTuple
(
'Point'
,
'x y'
)
p
=
Point
(
11
,
22
)
self
.
assert_
(
isinstance
(
p
,
tuple
))
self
.
assertEqual
(
p
,
(
11
,
22
))
# matches a real tuple
self
.
assertEqual
(
tuple
(
p
),
(
11
,
22
))
# coercable to a real tuple
self
.
assertEqual
(
list
(
p
),
[
11
,
22
])
# coercable to a list
self
.
assertEqual
(
max
(
p
),
22
)
# iterable
self
.
assertEqual
(
max
(
*
p
),
22
)
# star-able
x
,
y
=
p
self
.
assertEqual
(
p
,
(
x
,
y
))
# unpacks like a tuple
self
.
assertEqual
((
p
[
0
],
p
[
1
]),
(
11
,
22
))
# indexable like a tuple
self
.
assertRaises
(
IndexError
,
p
.
__getitem__
,
3
)
self
.
assertEqual
(
p
.
x
,
x
)
self
.
assertEqual
(
p
.
y
,
y
)
self
.
assertRaises
(
AttributeError
,
eval
,
'p.z'
,
locals
())
def
test_main
(
verbose
=
None
):
test_classes
=
[
TestNamedTuple
]
test_support
.
run_unittest
(
*
test_classes
)
if
__name__
==
"__main__"
:
test_main
(
verbose
=
True
)
Misc/NEWS
View file @
c37e5e04
...
...
@@ -138,6 +138,8 @@ Library
- Added heapq.merge() for merging sorted input streams.
- Added collections.NamedTuple() for assigning field names to tuples.
- Added itertools.izip_longest().
- Have the encoding package'
s
search
function
dynamically
import
using
absolute
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment