diff options
author | Raymond Hettinger <python@rcn.com> | 2003-11-23 02:49:05 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2003-11-23 02:49:05 (GMT) |
commit | 49ba4c39c49ff6b1db666e6c90365fc1361c4a64 (patch) | |
tree | 442b73b24c7d6590eb24f4b4d3b1a95465a23c23 /Objects/setobject.c | |
parent | baf0f8f24da7a541a403cd9848cebc451beb069d (diff) | |
download | cpython-49ba4c39c49ff6b1db666e6c90365fc1361c4a64.zip cpython-49ba4c39c49ff6b1db666e6c90365fc1361c4a64.tar.gz cpython-49ba4c39c49ff6b1db666e6c90365fc1361c4a64.tar.bz2 |
* Simplify hash function and add test to show effectiveness of the hash
function.
* Add a better test for deepcopying.
* Add tests to show the __init__() function works like it does for list
and tuple. Add related test.
* Have shallow copies of frozensets return self. Add related test.
* Have frozenset(f) return f if f is already a frozenset. Add related test.
* Beefed-up some existing tests.
Diffstat (limited to 'Objects/setobject.c')
-rw-r--r-- | Objects/setobject.c | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/Objects/setobject.c b/Objects/setobject.c index be73954..fab07fb 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -64,6 +64,10 @@ frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable)) return NULL; + if (iterable != NULL && iterable->ob_type == &PyFrozenSet_Type) { + Py_INCREF(iterable); + return iterable; + } return make_new_set(type, iterable); } @@ -154,6 +158,16 @@ set_copy(PySetObject *so) return (PyObject *)newso; } +static PyObject * +frozenset_copy(PySetObject *so) +{ + if (so->ob_type == &PyFrozenSet_Type) { + Py_INCREF(so); + return (PyObject *)so; + } + return set_copy(so); +} + PyDoc_STRVAR(copy_doc, "Return a shallow copy of a set."); static PyObject * @@ -686,7 +700,7 @@ frozenset_hash(PyObject *self) { PyObject *it, *item; PySetObject *so = (PySetObject *)self; - long hash = 0, x; + long hash = 0; if (so->hash != -1) return so->hash; @@ -696,14 +710,12 @@ frozenset_hash(PyObject *self) return -1; while ((item = PyIter_Next(it)) != NULL) { - x = PyObject_Hash(item); - /* Applying x*(x+1) breaks-up linear relationships so that - h(1) ^ h(2) will be less likely to coincide with hash(3). - Multiplying by a large prime increases the dispersion - between consecutive hashes. Adding one bit from the - original restores the one bit lost during the multiply - (all the products are even numbers). */ - hash ^= (x * (x+1) * 3644798167) | (x&1); + /* Multiplying by a large prime increases the bit dispersion for + closely spaced hash values. The is important because some + use cases have many combinations of a small number of + elements with nearby hashes so that many distinct combinations + collapse to only a handful of distinct hash values. */ + hash ^= PyObject_Hash(item) * 3644798167; Py_DECREF(item); } Py_DECREF(it); @@ -1096,17 +1108,17 @@ PyTypeObject PySet_Type = { static PyMethodDef frozenset_methods[] = { - {"copy", (PyCFunction)set_copy, METH_NOARGS, + {"copy", (PyCFunction)frozenset_copy, METH_NOARGS, copy_doc}, - {"__copy__", (PyCFunction)set_copy, METH_NOARGS, + {"__copy__", (PyCFunction)frozenset_copy, METH_NOARGS, copy_doc}, - {"difference",(PyCFunction)set_difference, METH_O, + {"difference", (PyCFunction)set_difference, METH_O, difference_doc}, {"intersection",(PyCFunction)set_intersection, METH_O, intersection_doc}, - {"issubset",(PyCFunction)set_issubset, METH_O, + {"issubset", (PyCFunction)set_issubset, METH_O, issubset_doc}, - {"issuperset",(PyCFunction)set_issuperset, METH_O, + {"issuperset", (PyCFunction)set_issuperset, METH_O, issuperset_doc}, {"__reduce__", (PyCFunction)set_reduce, METH_NOARGS, reduce_doc}, |