diff --git a/Include/abstract.h b/Include/abstract.h index 7e0bc4d6ad6..fd151735cea 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -422,20 +422,25 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ PyAPI_FUNC(int) PyObject_Length(PyObject *o); #define PyObject_Length PyObject_Size - PyAPI_FUNC(int) _PyObject_LengthCue(PyObject *o); + PyAPI_FUNC(int) _PyObject_LengthHint(PyObject *o); /* Return the size of object o. If the object, o, provides both sequence and mapping protocols, the sequence size is returned. On error, -1 is returned. If the object provides - a _length_cue() method, its value is returned. This is the + a __length_hint__() method, its value is returned. This is an + internal undocumented API provided for performance reasons; + for compatibility, don't use it outside the core. This is the equivalent to the Python expression: try: return len(o) except (AttributeError, TypeError): - if hasattr(o, '_length_cue'): - return o._length_cue() - raise + exc_type, exc_value, exc_tb = sys.exc_info() + try: + return o.__length_hint__() + except: + pass + raise exc_type, exc_value, exc_tb */ PyAPI_FUNC(PyObject *) PyObject_GetItem(PyObject *o, PyObject *key); diff --git a/Lib/test/test_iterlen.py b/Lib/test/test_iterlen.py index 1770de2c0ad..bcd0a6f4c2a 100644 --- a/Lib/test/test_iterlen.py +++ b/Lib/test/test_iterlen.py @@ -55,7 +55,9 @@ def len(obj): return _len(obj) except TypeError: try: - return obj._length_cue() + # note: this is an internal undocumented API, + # don't rely on it in your own programs + return obj.__length_hint__() except AttributeError: raise TypeError diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py index e26065c51a0..6ff12154aa0 100644 --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -607,7 +607,9 @@ class TestBasicOps(unittest.TestCase): for v in self.set: self.assert_(v in self.values) setiter = iter(self.set) - self.assertEqual(setiter._length_cue(), len(self.set)) + # note: __length_hint__ is an internal undocumented API, + # don't rely on it in your own programs + self.assertEqual(setiter.__length_hint__(), len(self.set)) def test_pickling(self): p = pickle.dumps(self.set) diff --git a/Modules/collectionsmodule.c b/Modules/collectionsmodule.c index 16f25dfaae0..20031549ee4 100644 --- a/Modules/collectionsmodule.c +++ b/Modules/collectionsmodule.c @@ -941,10 +941,10 @@ dequeiter_len(dequeiterobject *it) return PyInt_FromLong(it->counter); } -PyDoc_STRVAR(length_cue_doc, "Private method returning an estimate of len(list(it))."); +PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); static PyMethodDef dequeiter_methods[] = { - {"_length_cue", (PyCFunction)dequeiter_len, METH_NOARGS, length_cue_doc}, + {"__length_hint__", (PyCFunction)dequeiter_len, METH_NOARGS, length_hint_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index a7ecf93e9b2..4b8ed696cae 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -2346,10 +2346,10 @@ repeat_len(repeatobject *ro) return PyInt_FromLong(ro->cnt); } -PyDoc_STRVAR(length_cue_doc, "Private method returning an estimate of len(list(it))."); +PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); static PyMethodDef repeat_methods[] = { - {"_length_cue", (PyCFunction)repeat_len, METH_NOARGS, length_cue_doc}, + {"__length_hint__", (PyCFunction)repeat_len, METH_NOARGS, length_hint_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/abstract.c b/Objects/abstract.c index 8a5166ebf87..b794974b021 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -82,7 +82,7 @@ PyObject_Length(PyObject *o) #define PyObject_Length PyObject_Size int -_PyObject_LengthCue(PyObject *o) +_PyObject_LengthHint(PyObject *o) { int rv = PyObject_Size(o); if (rv != -1) @@ -92,7 +92,7 @@ _PyObject_LengthCue(PyObject *o) PyObject *err_type, *err_value, *err_tb, *ro; PyErr_Fetch(&err_type, &err_value, &err_tb); - ro = PyObject_CallMethod(o, "_length_cue", NULL); + ro = PyObject_CallMethod(o, "__length_hint__", NULL); if (ro != NULL) { rv = (int)PyInt_AsLong(ro); Py_DECREF(ro); @@ -1463,7 +1463,7 @@ PySequence_Tuple(PyObject *v) return NULL; /* Guess result size and allocate space. */ - n = _PyObject_LengthCue(v); + n = _PyObject_LengthHint(v); if (n < 0) { if (!PyErr_ExceptionMatches(PyExc_TypeError) && !PyErr_ExceptionMatches(PyExc_AttributeError)) { diff --git a/Objects/dictobject.c b/Objects/dictobject.c index cf88f340ea4..1deb26cc4d6 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2063,10 +2063,10 @@ dictiter_len(dictiterobject *di) return PyInt_FromLong(len); } -PyDoc_STRVAR(length_cue_doc, "Private method returning an estimate of len(list(it))."); +PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); static PyMethodDef dictiter_methods[] = { - {"_length_cue", (PyCFunction)dictiter_len, METH_NOARGS, length_cue_doc}, + {"__length_hint__", (PyCFunction)dictiter_len, METH_NOARGS, length_hint_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/enumobject.c b/Objects/enumobject.c index 8c3eab1692f..7a5d1a162a8 100644 --- a/Objects/enumobject.c +++ b/Objects/enumobject.c @@ -252,10 +252,10 @@ reversed_len(reversedobject *ro) return PyInt_FromLong((seqsize < position) ? 0 : position); } -PyDoc_STRVAR(length_cue_doc, "Private method returning an estimate of len(list(it))."); +PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); static PyMethodDef reversediter_methods[] = { - {"_length_cue", (PyCFunction)reversed_len, METH_NOARGS, length_cue_doc}, + {"__length_hint__", (PyCFunction)reversed_len, METH_NOARGS, length_hint_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/iterobject.c b/Objects/iterobject.c index fdee3ca9178..90dc3f0e3ad 100644 --- a/Objects/iterobject.c +++ b/Objects/iterobject.c @@ -87,10 +87,10 @@ iter_len(seqiterobject *it) return PyInt_FromLong(0); } -PyDoc_STRVAR(length_cue_doc, "Private method returning an estimate of len(list(it))."); +PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); static PyMethodDef seqiter_methods[] = { - {"_length_cue", (PyCFunction)iter_len, METH_NOARGS, length_cue_doc}, + {"__length_hint__", (PyCFunction)iter_len, METH_NOARGS, length_hint_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/listobject.c b/Objects/listobject.c index 04671f42196..8ba317a0e12 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -775,7 +775,7 @@ listextend(PyListObject *self, PyObject *b) iternext = *it->ob_type->tp_iternext; /* Guess a result list size. */ - n = _PyObject_LengthCue(b); + n = _PyObject_LengthHint(b); if (n < 0) { if (!PyErr_ExceptionMatches(PyExc_TypeError) && !PyErr_ExceptionMatches(PyExc_AttributeError)) { @@ -2776,10 +2776,10 @@ listiter_len(listiterobject *it) return PyInt_FromLong(0); } -PyDoc_STRVAR(length_cue_doc, "Private method returning an estimate of len(list(it))."); +PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); static PyMethodDef listiter_methods[] = { - {"_length_cue", (PyCFunction)listiter_len, METH_NOARGS, length_cue_doc}, + {"__length_hint__", (PyCFunction)listiter_len, METH_NOARGS, length_hint_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index 3cc5504631b..cfd9100d4d6 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -268,10 +268,10 @@ rangeiter_len(rangeiterobject *r) return PyInt_FromLong(r->len - r->index); } -PyDoc_STRVAR(length_cue_doc, "Private method returning an estimate of len(list(it))."); +PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); static PyMethodDef rangeiter_methods[] = { - {"_length_cue", (PyCFunction)rangeiter_len, METH_NOARGS, length_cue_doc}, + {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS, length_hint_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/setobject.c b/Objects/setobject.c index 2494baeab8f..baa2d01f418 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -758,10 +758,10 @@ setiter_len(setiterobject *si) return PyInt_FromLong(len); } -PyDoc_STRVAR(length_cue_doc, "Private method returning an estimate of len(list(it))."); +PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); static PyMethodDef setiter_methods[] = { - {"_length_cue", (PyCFunction)setiter_len, METH_NOARGS, length_cue_doc}, + {"__length_hint__", (PyCFunction)setiter_len, METH_NOARGS, length_hint_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 3fd311a483d..8ea29f03a96 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -860,10 +860,10 @@ tupleiter_len(tupleiterobject *it) return PyInt_FromLong(len); } -PyDoc_STRVAR(length_cue_doc, "Private method returning an estimate of len(list(it))."); +PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); static PyMethodDef tupleiter_methods[] = { - {"_length_cue", (PyCFunction)tupleiter_len, METH_NOARGS, length_cue_doc}, + {"__length_hint__", (PyCFunction)tupleiter_len, METH_NOARGS, length_hint_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index f8d23ad4cc9..362294f038a 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -220,7 +220,7 @@ builtin_filter(PyObject *self, PyObject *args) goto Fail_arg; /* Guess a result list size. */ - len = _PyObject_LengthCue(seq); + len = _PyObject_LengthHint(seq); if (len < 0) { if (!PyErr_ExceptionMatches(PyExc_TypeError) && !PyErr_ExceptionMatches(PyExc_AttributeError)) { @@ -875,7 +875,7 @@ builtin_map(PyObject *self, PyObject *args) } /* Update len. */ - curlen = _PyObject_LengthCue(curseq); + curlen = _PyObject_LengthHint(curseq); if (curlen < 0) { if (!PyErr_ExceptionMatches(PyExc_TypeError) && !PyErr_ExceptionMatches(PyExc_AttributeError)) { @@ -2111,7 +2111,7 @@ builtin_zip(PyObject *self, PyObject *args) len = -1; /* unknown */ for (i = 0; i < itemsize; ++i) { PyObject *item = PyTuple_GET_ITEM(args, i); - int thislen = _PyObject_LengthCue(item); + int thislen = _PyObject_LengthHint(item); if (thislen < 0) { if (!PyErr_ExceptionMatches(PyExc_TypeError) && !PyErr_ExceptionMatches(PyExc_AttributeError)) {