diff Python/bltinmodule.c @ 17667:76ee8b62ee2a legacy-trunk

Generalize max(seq) and min(seq) to work with iterators. NEEDS DOC CHANGES.
author Tim Peters <tim.peters@gmail.com>
date Thu, 03 May 2001 07:00:32 +0000
parents a97e18e499a9
children 0be277039d93
line wrap: on
line diff
--- a/Python/bltinmodule.c	Thu May 03 04:58:49 2001 +0000
+++ b/Python/bltinmodule.c	Thu May 03 07:00:32 2001 +0000
@@ -1444,30 +1444,37 @@
 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 @@
 			}
 			else if (cmp < 0) {
 				Py_DECREF(x);
-				Py_XDECREF(w);
+				Py_DECREF(w);
+				Py_DECREF(it);
 				return NULL;
 			}
 			else
@@ -1488,6 +1496,7 @@
 	if (w == NULL)
 		PyErr_SetString(PyExc_ValueError,
 				"min() or max() arg is an empty sequence");
+	Py_DECREF(it);
 	return w;
 }