From 45de5b2f81d6ef5ba0a45c0792403c230653ff1b Mon Sep 17 00:00:00 2001 From: Cloud User Date: Sat, 19 Jul 2025 07:53:07 -0400 Subject: [PATCH] Adding deepget method to dictionary --- Include/dictobject.h | 1 - Objects/clinic/dictobject.c.h | 40 +++++++++++++++++++++++++++++++++++ Objects/dictobject.c | 35 ++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/Include/dictobject.h b/Include/dictobject.h index 1bbeec1ab699e7..cfd286f9ce941c 100644 --- a/Include/dictobject.h +++ b/Include/dictobject.h @@ -17,7 +17,6 @@ PyAPI_DATA(PyTypeObject) PyDict_Type; #define PyDict_Check(op) \ PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_DICT_SUBCLASS) #define PyDict_CheckExact(op) Py_IS_TYPE((op), &PyDict_Type) - PyAPI_FUNC(PyObject *) PyDict_New(void); PyAPI_FUNC(PyObject *) PyDict_GetItem(PyObject *mp, PyObject *key); PyAPI_FUNC(PyObject *) PyDict_GetItemWithError(PyObject *mp, PyObject *key); diff --git a/Objects/clinic/dictobject.c.h b/Objects/clinic/dictobject.c.h index abf6b38449fcb0..0cf5d44d9a0fd0 100644 --- a/Objects/clinic/dictobject.c.h +++ b/Objects/clinic/dictobject.c.h @@ -113,6 +113,46 @@ dict_get(PyObject *self, PyObject *const *args, Py_ssize_t nargs) return return_value; } +PyDoc_STRVAR(dict_deepget__doc__, +"deepget($self, keys, default=None, /)\n" +"--\n" +"\n" +"Return the value for the nested keys if the full path exists in the dictionary, else return default."); + +#define DICT_DEEPGET_METHODDEF \ + {"deepget", _PyCFunction_CAST(dict_deepget), METH_FASTCALL, dict_deepget__doc__}, + +static PyObject * +dict_deepget_impl(PyDictObject *self, PyObject * const *keylist, PyObject *default_value); + +static PyObject * +dict_deepget(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *keylist; + PyObject *default_value = Py_None; + + if (!_PyArg_CheckPositional("deepget", nargs, 1, 2)) { + goto exit; + } + + keylist = args[0]; + if (!PyList_Check(keylist)) { + PyErr_SetString(PyExc_TypeError, "keys must be provided as a list"); + return NULL; + } + + if (nargs < 2) { + goto skip_optional; + } + default_value = args[1]; +skip_optional: + return_value = dict_deepget_impl((PyDictObject *)self, keylist, default_value); + +exit: + return return_value; +} + PyDoc_STRVAR(dict_setdefault__doc__, "setdefault($self, key, default=None, /)\n" "--\n" diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 0ed52ac5e87b6e..57acfda7e6cd3f 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -4312,6 +4312,40 @@ dict_get_impl(PyDictObject *self, PyObject *key, PyObject *default_value) return val; } +static PyObject * +dict_deepget_impl(PyDictObject *self, PyObject * const *keylist, PyObject *default_value) +{ + Py_ssize_t n = PyList_GET_SIZE(keylist); + if (n == 0) { + return default_value; + } + + PyObject *val = (PyObject *)self; // Start with top-level dict + for (Py_ssize_t i = 0; i < n; i++) { + PyObject *key = PyList_GET_ITEM(keylist, i); + + if (!PyDict_Check(val)) { + return default_value; + } + + Py_hash_t hash = _PyObject_HashFast(key); + if (hash == -1) { + dict_unhashable_type(key); + return default_value; + } + + PyObject *next = NULL; + Py_ssize_t ix = _Py_dict_lookup_threadsafe((PyDictObject *)val, key, hash, &next); + if (ix == DKIX_ERROR || ix == DKIX_EMPTY || next == NULL) { + return Py_NewRef(default_value); + } + + val = next; + } + + return Py_NewRef(val); +} + static int dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_value, PyObject **result, int incref_result) @@ -4741,6 +4775,7 @@ static PyMethodDef mapp_methods[] = { getitem__doc__}, DICT___SIZEOF___METHODDEF DICT_GET_METHODDEF + DICT_DEEPGET_METHODDEF DICT_SETDEFAULT_METHODDEF DICT_POP_METHODDEF DICT_POPITEM_METHODDEF pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy