From 96229b191814556622b575fd320e822f918f355a Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Fri, 11 Mar 2005 06:49:40 +0000 Subject: Add two new functions, any() and all(). --- Doc/lib/libfuncs.tex | 26 +++++++++++++++++++ Lib/test/test_builtin.py | 36 +++++++++++++++++++++++++++ Misc/NEWS | 2 ++ Python/bltinmodule.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+) diff --git a/Doc/lib/libfuncs.tex b/Doc/lib/libfuncs.tex index 6b853f3..9e387d9 100644 --- a/Doc/lib/libfuncs.tex +++ b/Doc/lib/libfuncs.tex @@ -60,6 +60,32 @@ def my_import(name): complex number, its magnitude is returned. \end{funcdesc} +\begin{funcdesc}{all}{iterable} + Return True if all elements of the \var{iterable} are true. + Equivalent to: + \begin{verbatim} + def all(iterable): + for element in iterable: + if not element: + return False + return True + \end{verbatim} + \versionadded{2.5} +\end{funcdesc} + +\begin{funcdesc}{any}{iterable} + Return True if any element of the \var{iterable} is true. + Equivalent to: + \begin{verbatim} + def any(iterable): + for element in iterable: + if element: + return True + return False + \end{verbatim} + \versionadded{2.5} +\end{funcdesc} + \begin{funcdesc}{basestring}{} This abstract type is the superclass for \class{str} and \class{unicode}. It cannot be called or instantiated, but it can be used to test whether diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 5aa9197..4e8ffe5 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -92,6 +92,14 @@ if have_unicode: (unichr(0x200), ValueError), ] +class TestFailingBool: + def __nonzero__(self): + raise RuntimeError + +class TestFailingIter: + def __iter__(self): + raise RuntimeError + class BuiltinTest(unittest.TestCase): def test_import(self): @@ -117,6 +125,34 @@ class BuiltinTest(unittest.TestCase): # str self.assertRaises(TypeError, abs, 'a') + def test_all(self): + self.assertEqual(all([2, 4, 6]), True) + self.assertEqual(all([2, None, 6]), False) + self.assertRaises(RuntimeError, all, [2, TestFailingBool(), 6]) + self.assertRaises(RuntimeError, all, TestFailingIter()) + self.assertRaises(TypeError, all, 10) # Non-iterable + self.assertRaises(TypeError, all) # No args + self.assertRaises(TypeError, all, [2, 4, 6], []) # Too many args + self.assertEqual(all([]), True) # Empty iterator + S = [50, 60] + self.assertEqual(all(x > 42 for x in S), True) + S = [50, 40, 60] + self.assertEqual(all(x > 42 for x in S), False) + + def test_any(self): + self.assertEqual(any([None, None, None]), False) + self.assertEqual(any([None, 4, None]), True) + self.assertRaises(RuntimeError, any, [None, TestFailingBool(), 6]) + self.assertRaises(RuntimeError, all, TestFailingIter()) + self.assertRaises(TypeError, any, 10) # Non-iterable + self.assertRaises(TypeError, any) # No args + self.assertRaises(TypeError, any, [2, 4, 6], []) # Too many args + self.assertEqual(any([]), False) # Empty iterator + S = [40, 60, 30] + self.assertEqual(any(x > 42 for x in S), True) + S = [10, 20, 30] + self.assertEqual(any(x > 42 for x in S), False) + def test_apply(self): def f0(*args): self.assertEqual(args, ()) diff --git a/Misc/NEWS b/Misc/NEWS index 3f4cbb1..19ce8f4 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ What's New in Python 2.5 alpha 1? Core and builtins ----------------- +- Added two new builtins, any() and all(). + - Defining a class with empty parentheses is now allowed (e.g., ``class C(): pass`` is no longer a syntax error) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 33b5ca5..145e946 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -68,6 +68,69 @@ PyDoc_STRVAR(abs_doc, \n\ Return the absolute value of the argument."); +static PyObject * +builtin_all(PyObject *self, PyObject *v) +{ + PyObject *it, *item; + + it = PyObject_GetIter(v); + if (it == NULL) + return NULL; + + while ((item = PyIter_Next(it)) != NULL) { + int cmp = PyObject_IsTrue(item); + Py_DECREF(item); + if (cmp < 0) { + Py_DECREF(it); + return NULL; + } + if (cmp == 0) { + Py_DECREF(it); + Py_RETURN_FALSE; + } + } + Py_DECREF(it); + if (PyErr_Occurred()) + return NULL; + Py_RETURN_TRUE; +} + +PyDoc_STRVAR(all_doc, +"all(iterable) -> bool\n\ +\n\ +Return True if bool(x) is True for all values x in the iterable."); + +static PyObject * +builtin_any(PyObject *self, PyObject *v) +{ + PyObject *it, *item; + + it = PyObject_GetIter(v); + if (it == NULL) + return NULL; + + while ((item = PyIter_Next(it)) != NULL) { + int cmp = PyObject_IsTrue(item); + Py_DECREF(item); + if (cmp < 0) { + Py_DECREF(it); + return NULL; + } + if (cmp == 1) { + Py_DECREF(it); + Py_RETURN_TRUE; + } + } + Py_DECREF(it); + if (PyErr_Occurred()) + return NULL; + Py_RETURN_FALSE; +} + +PyDoc_STRVAR(any_doc, +"any(iterable) -> bool\n\ +\n\ +Return True if bool(x) is True for any x in the iterable."); static PyObject * builtin_apply(PyObject *self, PyObject *args) @@ -2125,6 +2188,8 @@ in length to the length of the shortest argument sequence."); static PyMethodDef builtin_methods[] = { {"__import__", builtin___import__, METH_VARARGS, import_doc}, {"abs", builtin_abs, METH_O, abs_doc}, + {"all", builtin_all, METH_O, all_doc}, + {"any", builtin_any, METH_O, any_doc}, {"apply", builtin_apply, METH_VARARGS, apply_doc}, {"callable", builtin_callable, METH_O, callable_doc}, {"chr", builtin_chr, METH_VARARGS, chr_doc}, -- cgit v0.12