Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 00e9886

Browse files
committed
Add PyDict_SetDefault. (closes #17327)
Patch by Stefan Behnel and I.
1 parent 763edc1 commit 00e9886

5 files changed

Lines changed: 41 additions & 11 deletions

File tree

Doc/c-api/dict.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,15 @@ Dictionary Objects
110110
:c:type:`char\*`, rather than a :c:type:`PyObject\*`.
111111
112112
113+
.. c:function:: PyObject* PyDict_SetDefault(PyObject *p, PyObject *key, PyObject *default)
114+
115+
This is the same the Python-level :meth:`dict.setdefault`. If present, it
116+
returns the value corresponding to *key* from the dictionary *p*. If the key
117+
is not in the dict, it is inserted with value *defaultobj* and *defaultobj*
118+
is inserted. This function evaluates the hash function of *key* only once,
119+
instead of evaluating it independently for the lookup and the insertion.
120+
121+
113122
.. c:function:: PyObject* PyDict_Items(PyObject *p)
114123
115124
Return a :c:type:`PyListObject` containing all the items from the dictionary.

Doc/data/refcounts.dat

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,11 @@ PyDict_GetItemString:PyObject*::0:
220220
PyDict_GetItemString:PyObject*:p:0:
221221
PyDict_GetItemString:char*:key::
222222

223+
PyDict_SetDefault:PyObject*::0:
224+
PyDict_SetDefault:PyObject*:p:0:
225+
PyDict_SetDefault:PyObject*:key:0:conditionally +1 if inserted into the dict
226+
PyDict_SetDefault:PyObject*:default:0:conditionally +1 if inserted into the dict
227+
223228
PyDict_Items:PyObject*::+1:
224229
PyDict_Items:PyObject*:p:0:
225230

Include/dictobject.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ PyAPI_FUNC(PyObject *) PyDict_GetItem(PyObject *mp, PyObject *key);
5353
PyAPI_FUNC(PyObject *) PyDict_GetItemWithError(PyObject *mp, PyObject *key);
5454
PyAPI_FUNC(PyObject *) _PyDict_GetItemIdWithError(PyObject *dp,
5555
struct _Py_Identifier *key);
56+
PyAPI_FUNC(PyObject *) PyDict_SetDefault(
57+
PyObject *mp, PyObject *key, PyObject *defaultobj);
5658
PyAPI_FUNC(int) PyDict_SetItem(PyObject *mp, PyObject *key, PyObject *item);
5759
PyAPI_FUNC(int) PyDict_DelItem(PyObject *mp, PyObject *key);
5860
PyAPI_FUNC(void) PyDict_Clear(PyObject *mp);

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ What's New in Python 3.4.0 Alpha 1?
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #17327: Add PyDict_SetDefault.
14+
1315
- Issue #17032: The "global" in the "NameError: global name 'x' is not defined"
1416
error message has been removed. Patch by Ram Rachum.
1517

Objects/dictobject.c

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2211,19 +2211,19 @@ dict_get(register PyDictObject *mp, PyObject *args)
22112211
return val;
22122212
}
22132213

2214-
static PyObject *
2215-
dict_setdefault(register PyDictObject *mp, PyObject *args)
2214+
PyObject *
2215+
PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
22162216
{
2217-
PyObject *key;
2218-
PyObject *failobj = Py_None;
2217+
PyDictObject *mp = (PyDictObject *)d;
22192218
PyObject *val = NULL;
22202219
Py_hash_t hash;
22212220
PyDictKeyEntry *ep;
22222221
PyObject **value_addr;
22232222

2224-
if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &failobj))
2223+
if (!PyDict_Check(d)) {
2224+
PyErr_BadInternalCall();
22252225
return NULL;
2226-
2226+
}
22272227
if (!PyUnicode_CheckExact(key) ||
22282228
(hash = ((PyASCIIObject *) key)->hash) == -1) {
22292229
hash = PyObject_Hash(key);
@@ -2241,20 +2241,32 @@ dict_setdefault(register PyDictObject *mp, PyObject *args)
22412241
return NULL;
22422242
ep = find_empty_slot(mp, key, hash, &value_addr);
22432243
}
2244-
Py_INCREF(failobj);
2244+
Py_INCREF(defaultobj);
22452245
Py_INCREF(key);
2246-
MAINTAIN_TRACKING(mp, key, failobj);
2246+
MAINTAIN_TRACKING(mp, key, defaultobj);
22472247
ep->me_key = key;
22482248
ep->me_hash = hash;
2249-
*value_addr = failobj;
2250-
val = failobj;
2249+
*value_addr = defaultobj;
2250+
val = defaultobj;
22512251
mp->ma_keys->dk_usable--;
22522252
mp->ma_used++;
22532253
}
2254-
Py_INCREF(val);
22552254
return val;
22562255
}
22572256

2257+
static PyObject *
2258+
dict_setdefault(PyDictObject *mp, PyObject *args)
2259+
{
2260+
PyObject *key, *val;
2261+
PyObject *defaultobj = Py_None;
2262+
2263+
if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &defaultobj))
2264+
return NULL;
2265+
2266+
val = PyDict_SetDefault(mp, key, defaultobj);
2267+
Py_XINCREF(val);
2268+
return val;
2269+
}
22582270

22592271
static PyObject *
22602272
dict_clear(register PyDictObject *mp)

0 commit comments

Comments
 (0)