summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2002-04-12 15:11:59 (GMT)
committerGuido van Rossum <guido@python.org>2002-04-12 15:11:59 (GMT)
commite027d9818fdb15dd40ab4fd259dd1a33300cc597 (patch)
treeb3039c5a6f6280d60f3725f4885ac46a2d12981b
parentededa90f6779cfd7fdcf84306a98252913789a67 (diff)
downloadcpython-e027d9818fdb15dd40ab4fd259dd1a33300cc597.zip
cpython-e027d9818fdb15dd40ab4fd259dd1a33300cc597.tar.gz
cpython-e027d9818fdb15dd40ab4fd259dd1a33300cc597.tar.bz2
Add Raymond Hettinger's d.pop(). See SF patch 539949.
-rw-r--r--Doc/lib/libstdtypes.tex3
-rw-r--r--Lib/test/test_types.py15
-rw-r--r--Objects/dictobject.c38
3 files changed, 56 insertions, 0 deletions
diff --git a/Doc/lib/libstdtypes.tex b/Doc/lib/libstdtypes.tex
index f42f84e..a619105 100644
--- a/Doc/lib/libstdtypes.tex
+++ b/Doc/lib/libstdtypes.tex
@@ -992,6 +992,9 @@ arbitrary objects):
{\code{\var{a}[\var{k}]} if \code{\var{k} in \var{a}},
else \var{x} (also setting it)}
{(5)}
+ \lineiii{\var{a}.pop(\var{k})}
+ {remove specified \var{key} and return corresponding \var{value}}
+ {}
\lineiii{\var{a}.popitem()}
{remove and return an arbitrary (\var{key}, \var{value}) pair}
{(6)}
diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py
index 26535c4..9d4508b 100644
--- a/Lib/test/test_types.py
+++ b/Lib/test/test_types.py
@@ -476,6 +476,21 @@ try: d.popitem()
except KeyError: pass
else: raise TestFailed, "{}.popitem doesn't raise KeyError"
+# Tests for pop with specified key
+d.clear()
+k, v = 'abc', 'def'
+d[k] = v
+try: d.pop('ghi')
+except KeyError: pass
+else: raise TestFailed, "{}.pop(k) doesn't raise KeyError when k not in dictionary"
+
+if d.pop(k) != v: raise TestFailed, "{}.pop(k) doesn't find known key/value pair"
+if len(d) > 0: raise TestFailed, "{}.pop(k) failed to remove the specified pair"
+
+try: d.pop(k)
+except KeyError: pass
+else: raise TestFailed, "{}.pop(k) doesn't raise KeyError when dictionary is empty"
+
d[1] = 1
try:
for i in d:
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index ffc0579..1bd2f64 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -1495,6 +1495,39 @@ dict_clear(register dictobject *mp)
}
static PyObject *
+dict_pop(dictobject *mp, PyObject *key)
+{
+ long hash;
+ dictentry *ep;
+ PyObject *old_value, *old_key;
+
+ if (mp->ma_used == 0) {
+ PyErr_SetString(PyExc_KeyError,
+ "pop(): dictionary is empty");
+ return NULL;
+ }
+ if (!PyString_CheckExact(key) ||
+ (hash = ((PyStringObject *) key)->ob_shash) == -1) {
+ hash = PyObject_Hash(key);
+ if (hash == -1)
+ return NULL;
+ }
+ ep = (mp->ma_lookup)(mp, key, hash);
+ if (ep->me_value == NULL) {
+ PyErr_SetObject(PyExc_KeyError, key);
+ return NULL;
+ }
+ old_key = ep->me_key;
+ Py_INCREF(dummy);
+ ep->me_key = dummy;
+ old_value = ep->me_value;
+ ep->me_value = NULL;
+ mp->ma_used--;
+ Py_DECREF(old_key);
+ return old_value;
+}
+
+static PyObject *
dict_popitem(dictobject *mp)
{
int i = 0;
@@ -1636,6 +1669,9 @@ static char get__doc__[] =
static char setdefault_doc__[] =
"D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if not D.has_key(k)";
+static char pop__doc__[] =
+"D.pop(k) -> v, remove specified key and return the corresponding value";
+
static char popitem__doc__[] =
"D.popitem() -> (k, v), remove and return some (key, value) pair as a\n\
2-tuple; but raise KeyError if D is empty";
@@ -1674,6 +1710,8 @@ static PyMethodDef mapp_methods[] = {
get__doc__},
{"setdefault", (PyCFunction)dict_setdefault, METH_VARARGS,
setdefault_doc__},
+ {"pop", (PyCFunction)dict_pop, METH_O,
+ pop__doc__},
{"popitem", (PyCFunction)dict_popitem, METH_NOARGS,
popitem__doc__},
{"keys", (PyCFunction)dict_keys, METH_NOARGS,