Issue 2025: Add tuple.count() and tuple.index() to follow the ABC in collections.Sequence.

This commit is contained in:
Raymond Hettinger 2008-02-07 00:54:20 +00:00
parent 3c3d9ac46c
commit 5b07ebce86
3 changed files with 119 additions and 0 deletions

View File

@ -4,6 +4,7 @@ Tests common to tuple, list and UserList.UserList
import unittest import unittest
from test import test_support from test import test_support
import sys
# Various iterables # Various iterables
# This is used for checking the constructor (here and in test_deque.py) # This is used for checking the constructor (here and in test_deque.py)
@ -328,3 +329,64 @@ class CommonTest(unittest.TestCase):
self.assertEqual(a.__getitem__(slice(3,5)), self.type2test([])) self.assertEqual(a.__getitem__(slice(3,5)), self.type2test([]))
self.assertRaises(ValueError, a.__getitem__, slice(0, 10, 0)) self.assertRaises(ValueError, a.__getitem__, slice(0, 10, 0))
self.assertRaises(TypeError, a.__getitem__, 'x') self.assertRaises(TypeError, a.__getitem__, 'x')
def test_count(self):
a = self.type2test([0, 1, 2])*3
self.assertEqual(a.count(0), 3)
self.assertEqual(a.count(1), 3)
self.assertEqual(a.count(3), 0)
self.assertRaises(TypeError, a.count)
class BadExc(Exception):
pass
class BadCmp:
def __eq__(self, other):
if other == 2:
raise BadExc()
return False
self.assertRaises(BadExc, a.count, BadCmp())
def test_index(self):
u = self.type2test([0, 1])
self.assertEqual(u.index(0), 0)
self.assertEqual(u.index(1), 1)
self.assertRaises(ValueError, u.index, 2)
u = self.type2test([-2, -1, 0, 0, 1, 2])
self.assertEqual(u.count(0), 2)
self.assertEqual(u.index(0), 2)
self.assertEqual(u.index(0, 2), 2)
self.assertEqual(u.index(-2, -10), 0)
self.assertEqual(u.index(0, 3), 3)
self.assertEqual(u.index(0, 3, 4), 3)
self.assertRaises(ValueError, u.index, 2, 0, -10)
self.assertRaises(TypeError, u.index)
class BadExc(Exception):
pass
class BadCmp:
def __eq__(self, other):
if other == 2:
raise BadExc()
return False
a = self.type2test([0, 1, 2, 3])
self.assertRaises(BadExc, a.index, BadCmp())
a = self.type2test([-2, -1, 0, 0, 1, 2])
self.assertEqual(a.index(0), 2)
self.assertEqual(a.index(0, 2), 2)
self.assertEqual(a.index(0, -4), 2)
self.assertEqual(a.index(-2, -10), 0)
self.assertEqual(a.index(0, 3), 3)
self.assertEqual(a.index(0, -3), 3)
self.assertEqual(a.index(0, 3, 4), 3)
self.assertEqual(a.index(0, -3, -2), 3)
self.assertEqual(a.index(0, -4*sys.maxint, 4*sys.maxint), 2)
self.assertRaises(ValueError, a.index, 0, 4*sys.maxint,-4*sys.maxint)
self.assertRaises(ValueError, a.index, 2, 0, -10)

View File

@ -25,6 +25,9 @@ Core and builtins
- Issue #1678380: Fix a bug that identifies 0j and -0j when they appear - Issue #1678380: Fix a bug that identifies 0j and -0j when they appear
in the same code unit. in the same code unit.
- Issue #2025 : Add tuple.count() and tuple.index() methods to comply with
the collections.Sequence API.
- Patch #1970 by Antoine Pitrou: Speedup unicode whitespace and linebreak - Patch #1970 by Antoine Pitrou: Speedup unicode whitespace and linebreak
detection detection

View File

@ -455,6 +455,53 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n)
return (PyObject *) np; return (PyObject *) np;
} }
static PyObject *
tupleindex(PyTupleObject *self, PyObject *args)
{
Py_ssize_t i, start=0, stop=Py_SIZE(self);
PyObject *v;
if (!PyArg_ParseTuple(args, "O|O&O&:index", &v,
_PyEval_SliceIndex, &start,
_PyEval_SliceIndex, &stop))
return NULL;
if (start < 0) {
start += Py_SIZE(self);
if (start < 0)
start = 0;
}
if (stop < 0) {
stop += Py_SIZE(self);
if (stop < 0)
stop = 0;
}
for (i = start; i < stop && i < Py_SIZE(self); i++) {
int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);
if (cmp > 0)
return PyLong_FromSsize_t(i);
else if (cmp < 0)
return NULL;
}
PyErr_SetString(PyExc_ValueError, "tuple.index(x): x not in list");
return NULL;
}
static PyObject *
tuplecount(PyTupleObject *self, PyObject *v)
{
Py_ssize_t count = 0;
Py_ssize_t i;
for (i = 0; i < Py_SIZE(self); i++) {
int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);
if (cmp > 0)
count++;
else if (cmp < 0)
return NULL;
}
return PyLong_FromSsize_t(count);
}
static int static int
tupletraverse(PyTupleObject *o, visitproc visit, void *arg) tupletraverse(PyTupleObject *o, visitproc visit, void *arg)
{ {
@ -661,8 +708,15 @@ tuple_getnewargs(PyTupleObject *v)
} }
PyDoc_STRVAR(index_doc,
"T.index(value, [start, [stop]]) -> integer -- return first index of value");
PyDoc_STRVAR(count_doc,
"T.count(value) -> integer -- return number of occurrences of value");
static PyMethodDef tuple_methods[] = { static PyMethodDef tuple_methods[] = {
{"__getnewargs__", (PyCFunction)tuple_getnewargs, METH_NOARGS}, {"__getnewargs__", (PyCFunction)tuple_getnewargs, METH_NOARGS},
{"index", (PyCFunction)tupleindex, METH_VARARGS, index_doc},
{"count", (PyCFunction)tuplecount, METH_O, count_doc},
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };