[prev in list] [next in list] [prev in thread] [next in thread]
List: python-dev
Subject: [Python-Dev] First shot at some_set.get()
From: Willi Richert <w.richert () gmx ! net>
Date: 2009-10-23 10:23:08
Message-ID: 200910231223.08470.w.richert () gmx ! net
[Download RAW message or body]
Hi,
here is the first shot to provide a faster means of retrieving an arbitrary
element from a set without removing it.
The times for
=========================
from timeit import *
stat1 = "for i in xrange(100): iter(s).next()"
stat2 = "for i in xrange(100): s.get()"
for stat in [stat1, stat2]:
t = Timer(stat, setup="s=set(range(10000))") # outside the
try/except
try:
print t.timeit(number=1000)
except:
t.print_exc()
=========================
are
stat1: 0.0451760292053
stat2: 0.0148510932922
The patch is attached. Feel free to criticize.
I would love to see something like that in the standard Python interpreter.
Regards,
wr
["setobject_get.patch" (text/x-patch)]
Index: Objects/setobject.c
===================================================================
--- Objects/setobject.c (Revision 75593)
+++ Objects/setobject.c (Arbeitskopie)
@@ -757,6 +757,49 @@
PyDoc_STRVAR(pop_doc, "Remove and return an arbitrary set element.\n\
Raises KeyError if the set is empty.");
+static PyObject *
+set_get(PySetObject *so)
+{
+ register Py_ssize_t i = 0;
+ register setentry *entry;
+ PyObject *key;
+
+ assert (PyAnySet_Check(so));
+ if (so->used == 0) {
+ PyErr_SetString(PyExc_KeyError, "get from an empty set");
+ return NULL;
+ }
+
+ /* Set entry to "the first" unused or dummy set entry. We abuse
+ * the hash field of slot 0 to hold a search finger:
+ * If slot 0 has a value, use slot 0.
+ * Else slot 0 is being used to hold a search finger,
+ * and we use its hash value as the first index to look.
+ */
+ entry = &so->table[0];
+ if (entry->key == NULL || entry->key == dummy) {
+ i = entry->hash;
+ /* The hash field may be a real hash value, or it may be a
+ * legit search finger, or it may be a once-legit search
+ * finger that's out of bounds now because it wrapped around
+ * or the table shrunk -- simply make sure it's in bounds now.
+ */
+ if (i > so->mask || i < 1)
+ i = 1; /* skip slot 0 */
+ while ((entry = &so->table[i])->key == NULL || entry->key==dummy) {
+ i++;
+ if (i > so->mask)
+ i = 1;
+ }
+ }
+ key = entry->key;
+ Py_INCREF(key);
+ return key;
+}
+
+PyDoc_STRVAR(get_doc, "Return an arbitrary set element without removing it.\n\
+Raises KeyError if the set is empty.");
+
static int
set_traverse(PySetObject *so, visitproc visit, void *arg)
{
@@ -2043,6 +2086,8 @@
issuperset_doc},
{"pop", (PyCFunction)set_pop, METH_NOARGS,
pop_doc},
+ {"get", (PyCFunction)set_get, METH_NOARGS,
+ get_doc},
{"__reduce__", (PyCFunction)set_reduce, METH_NOARGS,
reduce_doc},
{"remove", (PyCFunction)set_remove, METH_O,
@@ -2355,6 +2400,16 @@
return set_pop((PySetObject *)set);
}
+PyObject *
+PySet_Get(PyObject *set)
+{
+ if (!PySet_Check(set)) {
+ PyErr_BadInternalCall();
+ return NULL;
+ }
+ return set_get((PySetObject *)set);
+}
+
int
_PySet_Update(PyObject *set, PyObject *iterable)
{
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: http://mail.python.org/mailman/options/python-dev/python-dev%40progressive-comp.com
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic