Expose dict_contains() and PyDict_Contains() with is about 10% faster
than PySequence_Contains() and more clearly applicable to dicts. Apply the new function in setobject.c where __contains__ checking is ubiquitous.
This commit is contained in:
parent
3972457de7
commit
bc0f2ab9bb
|
@ -1808,6 +1808,14 @@ format.
|
|||
Empties an existing dictionary of all key-value pairs.
|
||||
\end{cfuncdesc}
|
||||
|
||||
\begin{cfuncdesc}{int}{PyDict_Contains}{PyObject *p, PyObject *key}
|
||||
Determine if dictionary \var{p} contains \var{key}. If an item
|
||||
in \var{p} is matches \var{key}, return \code{1}, otherwise return
|
||||
\code{0}. On error, return \code{-1}. This is equivalent to the
|
||||
Python expression \samp{\var{key} in \var{p}}.
|
||||
\versionadded{2.4}
|
||||
\end{cfuncdesc}
|
||||
|
||||
\begin{cfuncdesc}{PyObject*}{PyDict_Copy}{PyObject *p}
|
||||
Returns a new dictionary that contains the same key-value pairs as
|
||||
\var{p}.
|
||||
|
|
|
@ -100,6 +100,7 @@ PyAPI_FUNC(PyObject *) PyDict_Values(PyObject *mp);
|
|||
PyAPI_FUNC(PyObject *) PyDict_Items(PyObject *mp);
|
||||
PyAPI_FUNC(int) PyDict_Size(PyObject *mp);
|
||||
PyAPI_FUNC(PyObject *) PyDict_Copy(PyObject *mp);
|
||||
PyAPI_FUNC(int) PyDict_Contains(PyObject *mp, PyObject *key);
|
||||
|
||||
/* PyDict_Update(mp, other) is equivalent to PyDict_Merge(mp, other, 1). */
|
||||
PyAPI_FUNC(int) PyDict_Update(PyObject *mp, PyObject *other);
|
||||
|
|
|
@ -231,6 +231,10 @@ Build
|
|||
C API
|
||||
-----
|
||||
|
||||
- Added a new function, PyDict_Contains(d, k) which is like
|
||||
PySequence_Contains() but is specific to dictionaries and executes
|
||||
about 10% faster.
|
||||
|
||||
- Added three new macros: Py_RETURN_NONE, Py_RETURN_TRUE, and Py_RETURN_FALSE.
|
||||
Each return the singleton they mention after Py_INCREF()ing them.
|
||||
|
||||
|
|
|
@ -1814,10 +1814,11 @@ static PyMethodDef mapp_methods[] = {
|
|||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
static int
|
||||
dict_contains(dictobject *mp, PyObject *key)
|
||||
int
|
||||
PyDict_Contains(PyObject *op, PyObject *key)
|
||||
{
|
||||
long hash;
|
||||
dictobject *mp = (dictobject *)op;
|
||||
|
||||
if (!PyString_CheckExact(key) ||
|
||||
(hash = ((PyStringObject *) key)->ob_shash) == -1) {
|
||||
|
@ -1837,7 +1838,7 @@ static PySequenceMethods dict_as_sequence = {
|
|||
0, /* sq_slice */
|
||||
0, /* sq_ass_item */
|
||||
0, /* sq_ass_slice */
|
||||
(objobjproc)dict_contains, /* sq_contains */
|
||||
(objobjproc)PyDict_Contains, /* sq_contains */
|
||||
0, /* sq_inplace_concat */
|
||||
0, /* sq_inplace_repeat */
|
||||
};
|
||||
|
|
|
@ -143,13 +143,13 @@ set_contains(PySetObject *so, PyObject *key)
|
|||
PyObject *tmp;
|
||||
int result;
|
||||
|
||||
result = PySequence_Contains(so->data, key);
|
||||
result = PyDict_Contains(so->data, key);
|
||||
if (result == -1 && PyAnySet_Check(key)) {
|
||||
PyErr_Clear();
|
||||
tmp = frozenset_dict_wrapper(((PySetObject *)(key))->data);
|
||||
if (tmp == NULL)
|
||||
return -1;
|
||||
result = PySequence_Contains(so->data, tmp);
|
||||
result = PyDict_Contains(so->data, tmp);
|
||||
Py_DECREF(tmp);
|
||||
}
|
||||
return result;
|
||||
|
@ -252,7 +252,7 @@ set_intersection(PySetObject *so, PyObject *other)
|
|||
}
|
||||
|
||||
while ((item = PyIter_Next(it)) != NULL) {
|
||||
if (PySequence_Contains(selfdata, item)) {
|
||||
if (PyDict_Contains(selfdata, item)) {
|
||||
if (PyDict_SetItem(tgtdata, item, Py_True) == -1) {
|
||||
Py_DECREF(it);
|
||||
Py_DECREF(result);
|
||||
|
@ -292,7 +292,7 @@ set_intersection_update(PySetObject *so, PyObject *other)
|
|||
|
||||
selfdata = so->data;
|
||||
while ((item = PyIter_Next(it)) != NULL) {
|
||||
if (PySequence_Contains(selfdata, item)) {
|
||||
if (PyDict_Contains(selfdata, item)) {
|
||||
if (PyDict_SetItem(newdict, item, Py_True) == -1) {
|
||||
Py_DECREF(newdict);
|
||||
Py_DECREF(it);
|
||||
|
@ -375,7 +375,7 @@ set_difference(PySetObject *so, PyObject *other)
|
|||
}
|
||||
|
||||
while ((item = PyIter_Next(it)) != NULL) {
|
||||
if (!PySequence_Contains(otherdata, item)) {
|
||||
if (!PyDict_Contains(otherdata, item)) {
|
||||
if (PyDict_SetItem(tgtdata, item, Py_True) == -1) {
|
||||
Py_XDECREF(otherset);
|
||||
Py_DECREF(it);
|
||||
|
@ -481,7 +481,7 @@ set_symmetric_difference_update(PySetObject *so, PyObject *other)
|
|||
return NULL;
|
||||
|
||||
while ((item = PyIter_Next(it)) != NULL) {
|
||||
if (PySequence_Contains(selfdata, item)) {
|
||||
if (PyDict_Contains(selfdata, item)) {
|
||||
if (PyDict_DelItem(selfdata, item) == -1) {
|
||||
Py_XDECREF(otherset);
|
||||
Py_DECREF(it);
|
||||
|
@ -541,7 +541,7 @@ set_symmetric_difference(PySetObject *so, PyObject *other)
|
|||
return NULL;
|
||||
}
|
||||
while ((item = PyIter_Next(it)) != NULL) {
|
||||
if (!PySequence_Contains(selfdata, item)) {
|
||||
if (!PyDict_Contains(selfdata, item)) {
|
||||
if (PyDict_SetItem(tgtdata, item, Py_True) == -1) {
|
||||
Py_DECREF(it);
|
||||
Py_DECREF(item);
|
||||
|
@ -562,7 +562,7 @@ set_symmetric_difference(PySetObject *so, PyObject *other)
|
|||
return NULL;
|
||||
}
|
||||
while ((item = PyIter_Next(it)) != NULL) {
|
||||
if (!PySequence_Contains(otherdata, item)) {
|
||||
if (!PyDict_Contains(otherdata, item)) {
|
||||
if (PyDict_SetItem(tgtdata, item, Py_True) == -1) {
|
||||
Py_DECREF(it);
|
||||
Py_DECREF(item);
|
||||
|
@ -634,7 +634,7 @@ set_issubset(PySetObject *so, PyObject *other)
|
|||
|
||||
otherdata = ((PySetObject *)other)->data;
|
||||
while ((item = PyIter_Next(it)) != NULL) {
|
||||
if (!PySequence_Contains(otherdata, item)) {
|
||||
if (!PyDict_Contains(otherdata, item)) {
|
||||
Py_DECREF(it);
|
||||
Py_DECREF(item);
|
||||
Py_RETURN_FALSE;
|
||||
|
|
Loading…
Reference in New Issue