]> granicus.if.org Git - python/commitdiff
Generalize max(seq) and min(seq) to work with iterators.
authorTim Peters <tim.peters@gmail.com>
Thu, 3 May 2001 07:00:32 +0000 (07:00 +0000)
committerTim Peters <tim.peters@gmail.com>
Thu, 3 May 2001 07:00:32 +0000 (07:00 +0000)
NEEDS DOC CHANGES.

Lib/test/test_iter.py
Misc/NEWS
Python/bltinmodule.c

index 952ab663522c1d27a8be4c2a210ef5c553189a93..64fc01e19dbeb7bc5a76033cf059c23fa8de57d8 100644 (file)
@@ -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, 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)
index bbd2ac3e01494ce5cfb9ae6d94bc44d8ab2a4718..9d84845744edc15c46dde565c8affc3a9f4655fe 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -19,6 +19,8 @@ Core
   arguments:
     filter()
     list()
+    max()
+    min()
 
 
 What's New in Python 2.1 (final)?
index 1051374fcf2f93fd1df599a128b83c98cc3fa36f..9e8a2279c0db7aa4729108d6d5d791a42aa7886c 100644 (file)
@@ -1444,30 +1444,37 @@ static PyObject *
 min_max(PyObject *args, int op)
 {
        int i;
-       PyObject *v, *w, *x;
-       PySequenceMethods *sq;
+       PyObject *v, *w, *x, *it;
 
        if (PyTuple_Size(args) > 1)
                v = args;
        else if (!PyArg_ParseTuple(args, "O:min/max", &v))
                return NULL;
-       sq = v->ob_type->tp_as_sequence;
-       if (sq == NULL || sq->sq_item == NULL) {
-               PyErr_SetString(PyExc_TypeError,
-                               "min() or max() arg must be a sequence");
+       
+       it = PyObject_GetIter(v);
+       if (it == NULL)
                return NULL;
-       }
-       w = NULL;
+
+       w = NULL;  /* the result */
        for (i = 0; ; i++) {
-               x = (*sq->sq_item)(v, i); /* Implies INCREF */
+               x = PyIter_Next(it);
                if (x == NULL) {
-                       if (PyErr_ExceptionMatches(PyExc_IndexError)) {
-                               PyErr_Clear();
-                               break;
+                       /* We're out of here in any case, but if this is a
+                        * StopIteration exception it's expected, but if
+                        * 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);
-                       return NULL;
+                       break;
                }
+
                if (w == NULL)
                        w = x;
                else {
@@ -1478,7 +1485,8 @@ min_max(PyObject *args, int op)
                        }
                        else if (cmp < 0) {
                                Py_DECREF(x);
-                               Py_XDECREF(w);
+                               Py_DECREF(w);
+                               Py_DECREF(it);
                                return NULL;
                        }
                        else
@@ -1488,6 +1496,7 @@ min_max(PyObject *args, int op)
        if (w == NULL)
                PyErr_SetString(PyExc_ValueError,
                                "min() or max() arg is an empty sequence");
+       Py_DECREF(it);
        return w;
 }