Generalize max(seq) and min(seq) to work with iterators.
NEEDS DOC CHANGES.
This commit is contained in:
parent
c7745d4b54
commit
c307453162
@ -319,4 +319,39 @@ class TestCase(unittest.TestCase):
|
|||||||
self.assertEqual(filter(lambda x: not x, seq), [False]*25)
|
self.assertEqual(filter(lambda x: not x, seq), [False]*25)
|
||||||
self.assertEqual(filter(lambda x: not x, iter(seq)), [False]*25)
|
self.assertEqual(filter(lambda x: not x, iter(seq)), [False]*25)
|
||||||
|
|
||||||
|
# Test max() and min()'s use of iterators.
|
||||||
|
def test_builtin_max_min(self):
|
||||||
|
self.assertEqual(max(SequenceClass(5)), 4)
|
||||||
|
self.assertEqual(min(SequenceClass(5)), 0)
|
||||||
|
self.assertEqual(max(8, -1), 8)
|
||||||
|
self.assertEqual(min(8, -1), -1)
|
||||||
|
|
||||||
|
d = {"one": 1, "two": 2, "three": 3}
|
||||||
|
self.assertEqual(max(d), "two")
|
||||||
|
self.assertEqual(min(d), "one")
|
||||||
|
self.assertEqual(max(d.itervalues()), 3)
|
||||||
|
self.assertEqual(min(iter(d.itervalues())), 1)
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, list, list)
|
||||||
|
self.assertRaises(TypeError, list, 42)
|
||||||
|
|
||||||
|
f = open(TESTFN, "w")
|
||||||
|
try:
|
||||||
|
f.write("medium line\n")
|
||||||
|
f.write("xtra large line\n")
|
||||||
|
f.write("itty-bitty line\n")
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
f = open(TESTFN, "r")
|
||||||
|
try:
|
||||||
|
self.assertEqual(min(f), "itty-bitty line\n")
|
||||||
|
f.seek(0, 0)
|
||||||
|
self.assertEqual(max(f), "xtra large line\n")
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
try:
|
||||||
|
unlink(TESTFN)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
run_unittest(TestCase)
|
run_unittest(TestCase)
|
||||||
|
@ -19,6 +19,8 @@ Core
|
|||||||
arguments:
|
arguments:
|
||||||
filter()
|
filter()
|
||||||
list()
|
list()
|
||||||
|
max()
|
||||||
|
min()
|
||||||
|
|
||||||
|
|
||||||
What's New in Python 2.1 (final)?
|
What's New in Python 2.1 (final)?
|
||||||
|
@ -1444,30 +1444,37 @@ static PyObject *
|
|||||||
min_max(PyObject *args, int op)
|
min_max(PyObject *args, int op)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
PyObject *v, *w, *x;
|
PyObject *v, *w, *x, *it;
|
||||||
PySequenceMethods *sq;
|
|
||||||
|
|
||||||
if (PyTuple_Size(args) > 1)
|
if (PyTuple_Size(args) > 1)
|
||||||
v = args;
|
v = args;
|
||||||
else if (!PyArg_ParseTuple(args, "O:min/max", &v))
|
else if (!PyArg_ParseTuple(args, "O:min/max", &v))
|
||||||
return NULL;
|
return NULL;
|
||||||
sq = v->ob_type->tp_as_sequence;
|
|
||||||
if (sq == NULL || sq->sq_item == NULL) {
|
it = PyObject_GetIter(v);
|
||||||
PyErr_SetString(PyExc_TypeError,
|
if (it == NULL)
|
||||||
"min() or max() arg must be a sequence");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
w = NULL;
|
w = NULL; /* the result */
|
||||||
for (i = 0; ; i++) {
|
for (i = 0; ; i++) {
|
||||||
x = (*sq->sq_item)(v, i); /* Implies INCREF */
|
x = PyIter_Next(it);
|
||||||
if (x == NULL) {
|
if (x == NULL) {
|
||||||
if (PyErr_ExceptionMatches(PyExc_IndexError)) {
|
/* We're out of here in any case, but if this is a
|
||||||
PyErr_Clear();
|
* StopIteration exception it's expected, but if
|
||||||
break;
|
* any other kind of exception it's an error.
|
||||||
|
*/
|
||||||
|
if (PyErr_Occurred()) {
|
||||||
|
if (PyErr_ExceptionMatches(PyExc_StopIteration))
|
||||||
|
PyErr_Clear();
|
||||||
|
else {
|
||||||
|
Py_XDECREF(w);
|
||||||
|
Py_DECREF(it);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Py_XDECREF(w);
|
break;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w == NULL)
|
if (w == NULL)
|
||||||
w = x;
|
w = x;
|
||||||
else {
|
else {
|
||||||
@ -1478,7 +1485,8 @@ min_max(PyObject *args, int op)
|
|||||||
}
|
}
|
||||||
else if (cmp < 0) {
|
else if (cmp < 0) {
|
||||||
Py_DECREF(x);
|
Py_DECREF(x);
|
||||||
Py_XDECREF(w);
|
Py_DECREF(w);
|
||||||
|
Py_DECREF(it);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1488,6 +1496,7 @@ min_max(PyObject *args, int op)
|
|||||||
if (w == NULL)
|
if (w == NULL)
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"min() or max() arg is an empty sequence");
|
"min() or max() arg is an empty sequence");
|
||||||
|
Py_DECREF(it);
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user