E57A Kill reduce(). A coproduction of John Reese, Jacques Frechet, and Al… · python/cpython@89da5d7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 89da5d7

Browse files
committed
Kill reduce(). A coproduction of John Reese, Jacques Frechet, and Alex M.
1 parent 6cefeb0 commit 89da5d7

File tree

10 files changed

+25
-144
lines changed

10 files changed

+25
-144
lines changed

Lib/csv.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -221,12 +221,10 @@ def _guess_quote_and_delimiter(self, data, delimiters):
221221
if m[n]:
222222
spaces += 1
223223

224-
quotechar = reduce(lambda a, b, quotes = quotes:
225-
(quotes[a] > quotes[b]) and a or b, quotes.keys())
224+
quotechar = max(quotes, key=quotes.get)
226225

227226
if delims:
228-
delim = reduce(lambda a, b, delims = delims:
229-
(delims[a] > delims[b]) and a or b, delims.keys())
227+
delim = max(delims, key=delims.get)
230228
skipinitialspace = delims[delim] == spaces
231229
if delim == '\n': # most likely a file with a single column
232230
delim = ''
@@ -285,14 +283,12 @@ def _guess_delimiter(self, data, delimiters):
285283
continue
286284
# get the mode of the frequencies
287285
if len(items) > 1:
288-
modes[char] = reduce(lambda a, b: a[1] > b[1] and a or b,
289-
items)
286+
modes[char] = max(items, key=lambda x: x[1])
290287
# adjust the mode - subtract the sum of all
291288
# other frequencies
292289
items.remove(modes[char])
293290
modes[char] = (modes[char][0], modes[char][1]
294-
- reduce(lambda a, b: (0, a[1] + b[1]),
295-
items)[1])
291+
- sum(item[1] for item in items))
296292
else:
297293
modes[char] = items[0]
298294

Lib/difflib.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -652,8 +652,7 @@ def ratio(self):
652652
1.0
653653
"""
654654

655-
matches = reduce(lambda sum, triple: sum + triple[-1],
656-
self.get_matching_blocks(), 0)
655+
matches = 9B9E sum(triple[-1] for triple in self.get_matching_blocks())
657656
return _calculate_ratio(matches, len(self.a) + len(self.b))
658657

659658
def quick_ratio(self):

Lib/idlelib/AutoCompleteWindow.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -335,10 +335,8 @@ def keypress_event(self, event):
335335
self.userwantswindow = True
336336
return
337337

338-
elif reduce(lambda x, y: x or y,
339-
[keysym.find(s) != -1 for s in ("Shift", "Control", "Alt",
340-
"Meta", "Command", "Option")
341-
]):
338+
elif any(s in keysym for s in ("Shift", "Control", "Alt",
339+
"Meta", "Command", "Option")):
342340
# A modifier key, so ignore
343341
return
344342

Lib/idlelib/MultiCall.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -106,24 +106,26 @@ def __del__(self):
106106
# _state_subsets gives for each combination of modifiers, or *state*,
107107
# a list of the states which are a subset of it. This list is ordered by the
108108
# number of modifiers is the state - the most specific state comes first.
109+
# XXX rewrite without overusing functional primitives :-)
109110
_states = range(1 << len(_modifiers))
110-
_state_names = [reduce(lambda x, y: x + y,
111-
[_modifiers[i][0]+'-' for i in range(len(_modifiers))
112-
if (1 << i) & s],
113-
"")
111+
_state_names = [''.join(m[0]+'-'
112+
for i, m in enumerate(_modifiers)
113+
if (1 << i) & s)
114114
for s in _states]
115115
_state_subsets = map(lambda i: filter(lambda j: not (j & (~i)), _states),
116-
_states)
116+
_states)
117117
for l in _state_subsets:
118118
l.sort(lambda a, b, nummod = lambda x: len(filter(lambda i: (1<<i) & x,
119119
range(len(_modifiers)))):
120120
nummod(b) - nummod(a))
121121
# _state_codes gives for each state, the portable code to be passed as mc_state
122-
_state_codes = [reduce(lambda x, y: x | y,
123-
[_modifier_masks[i] for i in range(len(_modifiers))
124-
if (1 << i) & s],
125-
0)
126-
for s in _states]
122+
_state_codes = []
123+
for s in _states:
124+
r = 0
125+
for i in range(len(_modifiers)):
126+
if (1 << i) & s:
127+
r |= _modifier_masks[i]
128+
_state_codes.append(r)
127129

128130
class _ComplexBinder:
129131
# This class binds many functions, and only unbinds them when it is deleted.

Lib/test/test_builtin.py

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,32 +1393,6 @@ def __cmp__(self, other):
13931393
self.assertRaises(OverflowError, range, -sys.maxint, sys.maxint)
13941394
self.assertRaises(OverflowError, range, 0, 2*sys.maxint)
13951395

1396-
def test_reduce(self):
1397-
self.assertEqual(reduce(lambda x, y: x+y, ['a', 'b', 'c'], ''), 'abc')
1398-
self.assertEqual(
1399-
reduce(lambda x, y: x+y, [['a', 'c'], [], ['d', 'w']], []),
1400-
['a','c','d','w']
1401-
)
1402-
self.assertEqual(reduce(lambda x, y: x*y, range(2,8), 1), 5040)
1403-
self.assertEqual(
1404-
reduce(lambda x, y: x*y, range(2,21), 1L),
1405-
2432902008176640000L
1406-
)
1407-
self.assertEqual(reduce(lambda x, y: x+y, Squares(10)), 285)
1408-
self.assertEqual(reduce(lambda x, y: x+y, Squares(10), 0), 285)
1409-
self.assertEqual(reduce(lambda x, y: x+y, Squares(0), 0), 0)
1410-
self.assertRaises(TypeError, reduce)
1411-
self.assertRaises(TypeError, reduce, 42, 42)
1412-
self.assertRaises(TypeError, reduce, 42, 42, 42)
1413-
self.assertEqual(reduce(42, "1"), "1") # func is never called with one item
1414-
self.assertEqual(reduce(42, "", "1"), "1") # func is never called with one item
1415-
self.assertRaises(TypeError, reduce, 42, (42, 42))
1416-
1417-
class BadSeq:
1418-
def __getitem__(self, index):
1419-
raise ValueError
1420-
self.assertRaises(ValueError, reduce, 42, BadSeq())
1421-
14221396
def test_reload(self):
14231397
import marshal
14241398
reload(marshal)

Lib/test/test_iter.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -498,19 +498,6 @@ def __len__(self):
498498
for y in NoGuessLen5(), Guess3Len5(), Guess30Len5():
499499
self.assertEqual(zip(x, y), expected)
500500

501-
# Test reduces()'s use of iterators.
502-
def test_builtin_reduce(self):
503-
from operator import add
504-
self.assertEqual(reduce(add, SequenceClass(5)), 10)
505-
self.assertEqual(reduce(add, SequenceClass(5), 42), 52)
506-
self.assertRaises(TypeError, reduce, add, SequenceClass(0))
507-
self.assertEqual(reduce(add, SequenceClass(0), 42), 42)
508-
self.assertEqual(reduce(add, SequenceClass(1)), 0)
509-
self.assertEqual(reduce(add, SequenceClass(1), 42), 42)
510-
511-
d = {"one": 1, "two": 2, "three": 3}
512-
self.assertEqual(reduce(add, d), "".join(d.keys()))
513-
514501
# This test case will be removed if we don't have Unicode
515502
def test_unicode_join_endcase(self):
516503

Lib/test/test_random.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ def test_sample_distribution(self):
7777
pop = range(n)
7878
trials = 10000 # large num prevents false negatives without slowing normal case
7979
def factorial(n):
80-
return reduce(int.__mul__, xrange(1, n), 1)
80+
if n == 0:
81+
return 1
82+
return n * factorial(n - 1)
8183
for k in xrange(n):
8284
expected = factorial(n) // factorial(n-k)
8385
perms = {}

Python/bltinmodule.c

Lines changed: 0 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,80 +1597,6 @@ For example, range(4) returns [0, 1, 2, 3]. The end point is omitted!\n\
15971597
These are exactly the valid indices for a list of 4 elements.");
15981598

15991599

1600-
static PyObject *
1601-
builtin_reduce(PyObject *self, PyObject *args)
1602-
{
1603-
PyObject *seq, *func, *result = NULL, *it;
1604-
1605-
if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
1606-
return NULL;
1607-
if (result != NULL)
1608-
Py_INCREF(result);
1609-
1610-
it = PyObject_GetIter(seq);
1611-
if (it == NULL) {
1612-
PyErr_SetString(PyExc_TypeError,
1613-
"reduce() arg 2 must support iteration");
1614-
Py_XDECREF(result);
1615-
return NULL;
1616-
}
1617-
1618-
if ((args = PyTuple_New(2)) == NULL)
1619-
goto Fail;
1620-
1621-
for (;;) {
1622-
PyObject *op2;
1623-
1624-
if (args->ob_refcnt > 1) {
1625-
Py_DECREF(args);
1626-
if ((args = PyTuple_New(2)) == NULL)
1627-
goto Fail;
1628-
}
1629-
1630-
op2 = PyIter_Next(it);
1631-
if (op2 == NULL) {
1632-
if (PyErr_Occurred())
1633-
goto Fail;
1634-
break;
1635-
}
1636-
1637-
if (result == NULL)
1638-
result = op2;
1639-
else {
1640-
PyTuple_SetItem(args, 0, result);
1641-
PyTuple_SetItem(args, 1, op2);
1642-
if ((result = PyEval_CallObject(func, args)) == NULL)
1643-
goto Fail;
1644-
}
1645-
}
1646-
1647-
Py_DECREF(args);
1648-
1649-
if (result == NULL)
1650-
PyErr_SetString(PyExc_TypeError,
1651-
"reduce() of empty sequence with no initial value");
1652-
1653-
Py_DECREF(it);
1654-
return result;
1655-
1656-
Fail:
1657-
Py_XDECREF(args);
1658-
Py_XDECREF(result);
1659-
Py_DECREF(it);
1660-
return NULL;
1661-
}
1662-
1663-
PyDoc_STRVAR(reduce_doc,
1664-
"reduce(function, sequence[, initial]) -> value\n\
1665-
\n\
1666-
Apply a function of two arguments cumulatively to the items of a sequence,\n\
1667-
from left to right, so as to reduce the sequence to a single value.\n\
1668-
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\
1669-
((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\
1670-
of the sequence in the calculation, and serves as a default when the\n\
1671-
sequence is empty.");
1672-
1673-
16741600
static PyObject *
16751601
builtin_reload(PyObject *self, PyObject *v)
16761602
{
@@ -2071,7 +1997,6 @@ static PyMethodDef builtin_methods[] = {
20711997
{"ord", builtin_ord, METH_O, ord_doc},
20721998
{"pow", builtin_pow, METH_VARARGS, pow_doc},
20731999
{"range", builtin_range, METH_VARARGS, range_doc},
2074-
{"reduce", builtin_reduce, METH_VARARGS, reduce_doc},
20752000
{"reload", builtin_reload, METH_O, reload_doc},
20762001
{"repr", builtin_repr, METH_O, repr_doc},
20772002
{"round", (PyCFunction)builtin_round, METH_VARARGS | METH_KEYWORDS, round_doc},

Tools/i18n/pygettext.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -462,12 +462,10 @@ def write(self, fp):
462462
rentries = reverse[rkey]
463463
rentries.sort()
464464
for k, v in rentries:
465-
isdocstring = 0
466465
# If the entry was gleaned out of a docstring, then add a
467466
# comment stating so. This is to aid translators who may wish
468467
# to skip translating some unimportant docstrings.
469-
if reduce(operator.__add__, v.values()):
470-
isdocstring = 1
468+
isdocstring = any(v.values())
471469
# k is the message string, v is a dictionary-set of 7022 (filename,
472470
# lineno) tuples. We want to sort the entries in v first by
473471
# file name and then by line number.

Tools/pybench/pybench.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ def stat(self):
370370
if runs == 0:
371371
return 0.0, 0.0, 0.0, 0.0
372372
min_time = min(self.times)
373-
total_time = reduce(operator.add, self.times, 0.0)
373+
total_time = sum(self.times)
374374
avg_time = total_time / float(runs)
375375
operation_avg = total_time / float(runs
376376
* self.rounds
@@ -570,7 +570,7 @@ def stat(self):
570570
if runs == 0:
571571
return 0.0, 0.0
572572
min_time = min(self.roundtimes)
573-
total_time = reduce(operator.add, self.roundtimes, 0.0)
573+
total_time = sum(self.roundtimes)
574574
avg_time = total_time / float(runs)
575575
max_time = max(self.roundtimes)
576576
return (min_time, avg_time, max_time)

0 commit comments

Comments
 (0)
0