diff options
author | Benjamin Peterson <benjamin@python.org> | 2013-03-08 03:16:29 (GMT) |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2013-03-08 03:16:29 (GMT) |
commit | 00e9886bd90490e1afc729a1abac384ba70fa6a1 (patch) | |
tree | 40c539d4a7866de9d9838a64c68e4a89c13d5a91 | |
parent | 763edc1c6a5a212f876c5b6b018a1d2d2054a334 (diff) | |
download | cpython-00e9886bd90490e1afc729a1abac384ba70fa6a1.zip cpython-00e9886bd90490e1afc729a1abac384ba70fa6a1.tar.gz cpython-00e9886bd90490e1afc729a1abac384ba70fa6a1.tar.bz2 |
Add PyDict_SetDefault. (closes #17327)
Patch by Stefan Behnel and I.
-rw-r--r-- | Doc/c-api/dict.rst | 9 | ||||
-rw-r--r-- | Doc/data/refcounts.dat | 5 | ||||
-rw-r--r-- | Include/dictobject.h | 2 | ||||
-rw-r--r-- | Misc/NEWS | 2 | ||||
-rw-r--r-- | Objects/dictobject.c | 34 |
5 files changed, 41 insertions, 11 deletions
diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst index 6bacc32..dc8ef53 100644 --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -110,6 +110,15 @@ Dictionary Objects :c:type:`char\*`, rather than a :c:type:`PyObject\*`. +.. c:function:: PyObject* PyDict_SetDefault(PyObject *p, PyObject *key, PyObject *default) + + This is the same the Python-level :meth:`dict.setdefault`. If present, it + returns the value corresponding to *key* from the dictionary *p*. If the key + is not in the dict, it is inserted with value *defaultobj* and *defaultobj* + is inserted. This function evaluates the hash function of *key* only once, + instead of evaluating it independently for the lookup and the insertion. + + .. c:function:: PyObject* PyDict_Items(PyObject *p) Return a :c:type:`PyListObject` containing all the items from the dictionary. diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index fac89af..e299050 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -220,6 +220,11 @@ PyDict_GetItemString:PyObject*::0: PyDict_GetItemString:PyObject*:p:0: PyDict_GetItemString:char*:key:: +PyDict_SetDefault:PyObject*::0: +PyDict_SetDefault:PyObject*:p:0: +PyDict_SetDefault:PyObject*:key:0:conditionally +1 if inserted into the dict +PyDict_SetDefault:PyObject*:default:0:conditionally +1 if inserted into the dict + PyDict_Items:PyObject*::+1: PyDict_Items:PyObject*:p:0: diff --git a/Include/dictobject.h b/Include/dictobject.h index d89aac8..16bd1d6 100644 --- a/Include/dictobject.h +++ b/Include/dictobject.h @@ -53,6 +53,8 @@ PyAPI_FUNC(PyObject *) PyDict_GetItem(PyObject *mp, PyObject *key); PyAPI_FUNC(PyObject *) PyDict_GetItemWithError(PyObject *mp, PyObject *key); PyAPI_FUNC(PyObject *) _PyDict_GetItemIdWithError(PyObject *dp, struct _Py_Identifier *key); +PyAPI_FUNC(PyObject *) PyDict_SetDefault( + PyObject *mp, PyObject *key, PyObject *defaultobj); PyAPI_FUNC(int) PyDict_SetItem(PyObject *mp, PyObject *key, PyObject *item); PyAPI_FUNC(int) PyDict_DelItem(PyObject *mp, PyObject *key); PyAPI_FUNC(void) PyDict_Clear(PyObject *mp); @@ -10,6 +10,8 @@ What's New in Python 3.4.0 Alpha 1? Core and Builtins ----------------- +- Issue #17327: Add PyDict_SetDefault. + - Issue #17032: The "global" in the "NameError: global name 'x' is not defined" error message has been removed. Patch by Ram Rachum. diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 9080ddf..2e8679f 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2211,19 +2211,19 @@ dict_get(register PyDictObject *mp, PyObject *args) return val; } -static PyObject * -dict_setdefault(register PyDictObject *mp, PyObject *args) +PyObject * +PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj) { - PyObject *key; - PyObject *failobj = Py_None; + PyDictObject *mp = (PyDictObject *)d; PyObject *val = NULL; Py_hash_t hash; PyDictKeyEntry *ep; PyObject **value_addr; - if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &failobj)) + if (!PyDict_Check(d)) { + PyErr_BadInternalCall(); return NULL; - + } if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *) key)->hash) == -1) { hash = PyObject_Hash(key); @@ -2241,20 +2241,32 @@ dict_setdefault(register PyDictObject *mp, PyObject *args) return NULL; ep = find_empty_slot(mp, key, hash, &value_addr); } - Py_INCREF(failobj); + Py_INCREF(defaultobj); Py_INCREF(key); - MAINTAIN_TRACKING(mp, key, failobj); + MAINTAIN_TRACKING(mp, key, defaultobj); ep->me_key = key; ep->me_hash = hash; - *value_addr = failobj; - val = failobj; + *value_addr = defaultobj; + val = defaultobj; mp->ma_keys->dk_usable--; mp->ma_used++; } - Py_INCREF(val); return val; } +static PyObject * +dict_setdefault(PyDictObject *mp, PyObject *args) +{ + PyObject *key, *val; + PyObject *defaultobj = Py_None; + + if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &defaultobj)) + return NULL; + + val = PyDict_SetDefault(mp, key, defaultobj); + Py_XINCREF(val); + return val; +} static PyObject * dict_clear(register PyDictObject *mp) |