mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 19:34:08 +00:00 
			
		
		
		
	Generalize max(seq) and min(seq) to work with iterators.
NEEDS DOC CHANGES.
This commit is contained in:
		
							parent
							
								
									c7745d4b54
								
							
						
					
					
						commit
						c307453162
					
				
					 3 changed files with 61 additions and 15 deletions
				
			
		| 
						 | 
					@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue