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
e25d5fc1
Commit
e25d5fc1
authored
Oct 25, 2018
by
madman-bob
Committed by
Victor Stinner
Oct 25, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bpo-32321: Add pure Python fallback for functools.reduce (GH-8548)
parent
6279c1c5
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
80 additions
and
36 deletions
+80
-36
Lib/functools.py
Lib/functools.py
+39
-4
Lib/test/test_functools.py
Lib/test/test_functools.py
+39
-32
Misc/NEWS.d/next/Library/2018-07-29-13-50-32.bpo-32321.hDoNKC.rst
...S.d/next/Library/2018-07-29-13-50-32.bpo-32321.hDoNKC.rst
+2
-0
No files found.
Lib/functools.py
View file @
e25d5fc1
...
...
@@ -13,10 +13,6 @@ __all__ = ['update_wrapper', 'wraps', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES',
'total_ordering'
,
'cmp_to_key'
,
'lru_cache'
,
'reduce'
,
'partial'
,
'partialmethod'
,
'singledispatch'
,
'singledispatchmethod'
]
try
:
from
_functools
import
reduce
except
ImportError
:
pass
from
abc
import
get_cache_token
from
collections
import
namedtuple
# import types, weakref # Deferred to single_dispatch()
...
...
@@ -226,6 +222,45 @@ except ImportError:
pass
################################################################################
### reduce() sequence to a single item
################################################################################
_initial_missing
=
object
()
def
reduce
(
function
,
sequence
,
initial
=
_initial_missing
):
"""
reduce(function, sequence[, initial]) -> value
Apply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
((((1+2)+3)+4)+5). If initial is present, it is placed before the items
of the sequence in the calculation, and serves as a default when the
sequence is empty.
"""
it
=
iter
(
sequence
)
if
initial
is
_initial_missing
:
try
:
value
=
next
(
it
)
except
StopIteration
:
raise
TypeError
(
"reduce() of empty sequence with no initial value"
)
from
None
else
:
value
=
initial
for
element
in
it
:
value
=
function
(
value
,
element
)
return
value
try
:
from
_functools
import
reduce
except
ImportError
:
pass
################################################################################
### partial() argument application
################################################################################
...
...
Lib/test/test_functools.py
View file @
e25d5fc1
...
...
@@ -746,11 +746,8 @@ class TestWraps(TestUpdateWrapper):
self
.
assertEqual
(
wrapper
.
attr
,
'This is a different test'
)
self
.
assertEqual
(
wrapper
.
dict_attr
,
f
.
dict_attr
)
@
unittest
.
skipUnless
(
c_functools
,
'requires the C _functools module'
)
class
TestReduce
(
unittest
.
TestCase
):
if
c_functools
:
func
=
c_functools
.
reduce
class
TestReduce
:
def
test_reduce
(
self
):
class
Squares
:
def
__init__
(
self
,
max
):
...
...
@@ -769,42 +766,42 @@ class TestReduce(unittest.TestCase):
return
self
.
sofar
[
i
]
def
add
(
x
,
y
):
return
x
+
y
self
.
assertEqual
(
self
.
func
(
add
,
[
'a'
,
'b'
,
'c'
],
''
),
'abc'
)
self
.
assertEqual
(
self
.
reduce
(
add
,
[
'a'
,
'b'
,
'c'
],
''
),
'abc'
)
self
.
assertEqual
(
self
.
func
(
add
,
[[
'a'
,
'c'
],
[],
[
'd'
,
'w'
]],
[]),
self
.
reduce
(
add
,
[[
'a'
,
'c'
],
[],
[
'd'
,
'w'
]],
[]),
[
'a'
,
'c'
,
'd'
,
'w'
]
)
self
.
assertEqual
(
self
.
func
(
lambda
x
,
y
:
x
*
y
,
range
(
2
,
8
),
1
),
5040
)
self
.
assertEqual
(
self
.
reduce
(
lambda
x
,
y
:
x
*
y
,
range
(
2
,
8
),
1
),
5040
)
self
.
assertEqual
(
self
.
func
(
lambda
x
,
y
:
x
*
y
,
range
(
2
,
21
),
1
),
self
.
reduce
(
lambda
x
,
y
:
x
*
y
,
range
(
2
,
21
),
1
),
2432902008176640000
)
self
.
assertEqual
(
self
.
func
(
add
,
Squares
(
10
)),
285
)
self
.
assertEqual
(
self
.
func
(
add
,
Squares
(
10
),
0
),
285
)
self
.
assertEqual
(
self
.
func
(
add
,
Squares
(
0
),
0
),
0
)
self
.
assertRaises
(
TypeError
,
self
.
func
)
self
.
assertRaises
(
TypeError
,
self
.
func
,
42
,
42
)
self
.
assertRaises
(
TypeError
,
self
.
func
,
42
,
42
,
42
)
self
.
assertEqual
(
self
.
func
(
42
,
"1"
),
"1"
)
# func is never called with one item
self
.
assertEqual
(
self
.
func
(
42
,
""
,
"1"
),
"1"
)
# func is never called with one item
self
.
assertRaises
(
TypeError
,
self
.
func
,
42
,
(
42
,
42
))
self
.
assertRaises
(
TypeError
,
self
.
func
,
add
,
[])
# arg 2 must not be empty sequence with no initial value
self
.
assertRaises
(
TypeError
,
self
.
func
,
add
,
""
)
self
.
assertRaises
(
TypeError
,
self
.
func
,
add
,
())
self
.
assertRaises
(
TypeError
,
self
.
func
,
add
,
object
())
self
.
assertEqual
(
self
.
reduce
(
add
,
Squares
(
10
)),
285
)
self
.
assertEqual
(
self
.
reduce
(
add
,
Squares
(
10
),
0
),
285
)
self
.
assertEqual
(
self
.
reduce
(
add
,
Squares
(
0
),
0
),
0
)
self
.
assertRaises
(
TypeError
,
self
.
reduce
)
self
.
assertRaises
(
TypeError
,
self
.
reduce
,
42
,
42
)
self
.
assertRaises
(
TypeError
,
self
.
reduce
,
42
,
42
,
42
)
self
.
assertEqual
(
self
.
reduce
(
42
,
"1"
),
"1"
)
# func is never called with one item
self
.
assertEqual
(
self
.
reduce
(
42
,
""
,
"1"
),
"1"
)
# func is never called with one item
self
.
assertRaises
(
TypeError
,
self
.
reduce
,
42
,
(
42
,
42
))
self
.
assertRaises
(
TypeError
,
self
.
reduce
,
add
,
[])
# arg 2 must not be empty sequence with no initial value
self
.
assertRaises
(
TypeError
,
self
.
reduce
,
add
,
""
)
self
.
assertRaises
(
TypeError
,
self
.
reduce
,
add
,
())
self
.
assertRaises
(
TypeError
,
self
.
reduce
,
add
,
object
())
class
TestFailingIter
:
def
__iter__
(
self
):
raise
RuntimeError
self
.
assertRaises
(
RuntimeError
,
self
.
func
,
add
,
TestFailingIter
())
self
.
assertRaises
(
RuntimeError
,
self
.
reduce
,
add
,
TestFailingIter
())
self
.
assertEqual
(
self
.
func
(
add
,
[],
None
),
None
)
self
.
assertEqual
(
self
.
func
(
add
,
[],
42
),
42
)
self
.
assertEqual
(
self
.
reduce
(
add
,
[],
None
),
None
)
self
.
assertEqual
(
self
.
reduce
(
add
,
[],
42
),
42
)
class
BadSeq
:
def
__getitem__
(
self
,
index
):
raise
ValueError
self
.
assertRaises
(
ValueError
,
self
.
func
,
42
,
BadSeq
())
self
.
assertRaises
(
ValueError
,
self
.
reduce
,
42
,
BadSeq
())
# Test reduce()'s use of iterators.
def
test_iterator_usage
(
self
):
...
...
@@ -818,15 +815,25 @@ class TestReduce(unittest.TestCase):
raise
IndexError
from
operator
import
add
self
.
assertEqual
(
self
.
func
(
add
,
SequenceClass
(
5
)),
10
)
self
.
assertEqual
(
self
.
func
(
add
,
SequenceClass
(
5
),
42
),
52
)
self
.
assertRaises
(
TypeError
,
self
.
func
,
add
,
SequenceClass
(
0
))
self
.
assertEqual
(
self
.
func
(
add
,
SequenceClass
(
0
),
42
),
42
)
self
.
assertEqual
(
self
.
func
(
add
,
SequenceClass
(
1
)),
0
)
self
.
assertEqual
(
self
.
func
(
add
,
SequenceClass
(
1
),
42
),
42
)
self
.
assertEqual
(
self
.
reduce
(
add
,
SequenceClass
(
5
)),
10
)
self
.
assertEqual
(
self
.
reduce
(
add
,
SequenceClass
(
5
),
42
),
52
)
self
.
assertRaises
(
TypeError
,
self
.
reduce
,
add
,
SequenceClass
(
0
))
self
.
assertEqual
(
self
.
reduce
(
add
,
SequenceClass
(
0
),
42
),
42
)
self
.
assertEqual
(
self
.
reduce
(
add
,
SequenceClass
(
1
)),
0
)
self
.
assertEqual
(
self
.
reduce
(
add
,
SequenceClass
(
1
),
42
),
42
)
d
=
{
"one"
:
1
,
"two"
:
2
,
"three"
:
3
}
self
.
assertEqual
(
self
.
func
(
add
,
d
),
""
.
join
(
d
.
keys
()))
self
.
assertEqual
(
self
.
reduce
(
add
,
d
),
""
.
join
(
d
.
keys
()))
@
unittest
.
skipUnless
(
c_functools
,
'requires the C _functools module'
)
class
TestReduceC
(
TestReduce
,
unittest
.
TestCase
):
if
c_functools
:
reduce
=
c_functools
.
reduce
class
TestReducePy
(
TestReduce
,
unittest
.
TestCase
):
reduce
=
staticmethod
(
py_functools
.
reduce
)
class
TestCmpToKey
:
...
...
Misc/NEWS.d/next/Library/2018-07-29-13-50-32.bpo-32321.hDoNKC.rst
0 → 100644
View file @
e25d5fc1
Add pure Python fallback for functools.reduce.
Patch by Robert Wright.
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