[Python-checkins] r87265 - in python/branches/py3k: Lib/collections.py Misc/NEWS Modules/_collectionsmodule.c
raymond.hettinger
python-checkins at python.org
Wed Dec 15 17:30:37 CET 2010
Author: raymond.hettinger
Date: Wed Dec 15 17:30:37 2010
New Revision: 87265
Log:
Issue 10667: Fast path for collections.Counter
Modified:
python/branches/py3k/Lib/collections.py
python/branches/py3k/Misc/NEWS
python/branches/py3k/Modules/_collectionsmodule.c
Modified: python/branches/py3k/Lib/collections.py
==============================================================================
--- python/branches/py3k/Lib/collections.py (original)
+++ python/branches/py3k/Lib/collections.py Wed Dec 15 17:30:37 2010
@@ -334,6 +334,17 @@
### Counter
########################################################################
+def _count_elements(mapping, iterable):
+ 'Tally elements from the iterable.'
+ mapping_get = mapping.get
+ for elem in iterable:
+ mapping[elem] = mapping_get(elem, 0) + 1
+
+try: # Load C helper function if available
+ from _collections import _count_elements
+except ImportError:
+ pass
+
class Counter(dict):
'''Dict subclass for counting hashable items. Sometimes called a bag
or multiset. Elements are stored as dictionary keys and their counts
@@ -476,9 +487,7 @@
else:
dict.update(self, iterable) # fast path when counter is empty
else:
- self_get = self.get
- for elem in iterable:
- self[elem] = 1 + self_get(elem, 0)
+ _count_elements(self, iterable)
if kwds:
self.update(kwds)
Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS (original)
+++ python/branches/py3k/Misc/NEWS Wed Dec 15 17:30:37 2010
@@ -17,6 +17,8 @@
Library
-------
+- Issue #10667: Fast path for collections.Counter().
+
- Issue #10695: passing the port as a string value to telnetlib no longer
causes debug mode to fail.
Modified: python/branches/py3k/Modules/_collectionsmodule.c
==============================================================================
--- python/branches/py3k/Modules/_collectionsmodule.c (original)
+++ python/branches/py3k/Modules/_collectionsmodule.c Wed Dec 15 17:30:37 2010
@@ -1518,6 +1518,68 @@
PyObject_GC_Del, /* tp_free */
};
+/* helper function for Counter *********************************************/
+
+PyDoc_STRVAR(_count_elements_doc,
+"_count_elements(mapping, iterable) -> None\n\
+\n\
+Count elements in the iterable, updating the mappping");
+
+static PyObject *
+_count_elements(PyObject *self, PyObject *args)
+{
+ PyObject *it, *iterable, *mapping, *oldval;
+ PyObject *newval = NULL;
+ PyObject *key = NULL;
+ PyObject *one = NULL;
+
+ if (!PyArg_UnpackTuple(args, "_count_elements", 2, 2, &mapping, &iterable))
+ return NULL;
+
+ if (!PyDict_Check(mapping)) {
+ PyErr_SetString(PyExc_TypeError,
+ "Expected mapping argument to be a dictionary");
+ return NULL;
+ }
+
+ it = PyObject_GetIter(iterable);
+ if (it == NULL)
+ return NULL;
+ one = PyLong_FromLong(1);
+ if (one == NULL) {
+ Py_DECREF(it);
+ return NULL;
+ }
+ while (1) {
+ key = PyIter_Next(it);
+ if (key == NULL) {
+ if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration))
+ PyErr_Clear();
+ break;
+ }
+ oldval = PyDict_GetItem(mapping, key);
+ if (oldval == NULL) {
+ if (PyDict_SetItem(mapping, key, one) == -1)
+ break;
+ } else {
+ newval = PyNumber_Add(oldval, one);
+ if (newval == NULL)
+ break;
+ if (PyDict_SetItem(mapping, key, newval) == -1)
+ break;
+ Py_CLEAR(newval);
+ }
+ Py_DECREF(key);
+ }
+ Py_DECREF(it);
+ Py_XDECREF(key);
+ Py_XDECREF(newval);
+ Py_DECREF(one);
+ if (PyErr_Occurred())
+ return NULL;
+ Py_RETURN_NONE;
+}
+
/* module level code ********************************************************/
PyDoc_STRVAR(module_doc,
@@ -1526,13 +1588,17 @@
- defaultdict: dict subclass with a default value factory\n\
");
+static struct PyMethodDef module_functions[] = {
+ {"_count_elements", _count_elements, METH_VARARGS, _count_elements_doc},
+ {NULL, NULL} /* sentinel */
+};
static struct PyModuleDef _collectionsmodule = {
PyModuleDef_HEAD_INIT,
"_collections",
module_doc,
-1,
- NULL,
+ module_functions,
NULL,
NULL,
NULL,
More information about the Python-checkins
mailing list