SF patch #693753: fix for bug 639806: default for dict.pop
(contributed by Michael Stone.)
This commit is contained in:
parent
2b4821347f
commit
a3e1e4cd79
@ -1104,9 +1104,10 @@ arbitrary objects):
|
|||||||
{\code{\var{a}[\var{k}]} if \code{\var{k} in \var{a}},
|
{\code{\var{a}[\var{k}]} if \code{\var{k} in \var{a}},
|
||||||
else \var{x} (also setting it)}
|
else \var{x} (also setting it)}
|
||||||
{(5)}
|
{(5)}
|
||||||
\lineiii{\var{a}.pop(\var{k})}
|
\lineiii{\var{a}.pop(\var{k}\optional{, \var{x}})}
|
||||||
{remove specified \var{key} and return corresponding \var{value}}
|
{\code{\var{a}[\var{k}]} if \code{\var{k} in \var{a}},
|
||||||
{}
|
else \var{x} (and remove k)}
|
||||||
|
{(8)}
|
||||||
\lineiii{\var{a}.popitem()}
|
\lineiii{\var{a}.popitem()}
|
||||||
{remove and return an arbitrary (\var{key}, \var{value}) pair}
|
{remove and return an arbitrary (\var{key}, \var{value}) pair}
|
||||||
{(6)}
|
{(6)}
|
||||||
@ -1155,6 +1156,9 @@ over a dictionary, as often used in set algorithms.
|
|||||||
|
|
||||||
\item[(7)] \function{fromkeys()} is a class method that returns a
|
\item[(7)] \function{fromkeys()} is a class method that returns a
|
||||||
new dictionary. \var{value} defaults to \code{None}. \versionadded{2.3}
|
new dictionary. \var{value} defaults to \code{None}. \versionadded{2.3}
|
||||||
|
|
||||||
|
\item[(8)] \function{pop()} raises a \exception{KeyError} when no default
|
||||||
|
value is given and the key is not found. \versionadded{2.3}
|
||||||
\end{description}
|
\end{description}
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,8 +55,8 @@ class UserDict:
|
|||||||
if not self.has_key(key):
|
if not self.has_key(key):
|
||||||
self[key] = failobj
|
self[key] = failobj
|
||||||
return self[key]
|
return self[key]
|
||||||
def pop(self, key):
|
def pop(self, key, *args):
|
||||||
return self.data.pop(key)
|
return self.data.pop(key, *args)
|
||||||
def popitem(self):
|
def popitem(self):
|
||||||
return self.data.popitem()
|
return self.data.popitem()
|
||||||
def __contains__(self, key):
|
def __contains__(self, key):
|
||||||
@ -117,8 +117,16 @@ class DictMixin:
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
self[key] = default
|
self[key] = default
|
||||||
return default
|
return default
|
||||||
def pop(self, key):
|
def pop(self, key, *args):
|
||||||
value = self[key]
|
if len(args) > 1:
|
||||||
|
raise TypeError, "pop expected at most 2 arguments, got "\
|
||||||
|
+ repr(1 + len(args))
|
||||||
|
try:
|
||||||
|
value = self[key]
|
||||||
|
except KeyError:
|
||||||
|
if args:
|
||||||
|
return args[0]
|
||||||
|
raise
|
||||||
del self[key]
|
del self[key]
|
||||||
return value
|
return value
|
||||||
def popitem(self):
|
def popitem(self):
|
||||||
|
@ -643,10 +643,14 @@ else: raise TestFailed, "{}.pop(k) doesn't raise KeyError when dictionary is emp
|
|||||||
# see SF bug #689659
|
# see SF bug #689659
|
||||||
x = 4503599627370496L
|
x = 4503599627370496L
|
||||||
y = 4503599627370496
|
y = 4503599627370496
|
||||||
h = {x: 'anything', y: 'something else'}
|
h = {x: 'anything', y: 'something else'}
|
||||||
if h[x] != h[y]:
|
if h[x] != h[y]:
|
||||||
raise TestFailed, "long/int key should match"
|
raise TestFailed, "long/int key should match"
|
||||||
|
|
||||||
|
if d.pop(k, v) != v: raise TestFailed, "{}.pop(k, v) doesn't return default value"
|
||||||
|
d[k] = v
|
||||||
|
if d.pop(k, 1) != v: raise TestFailed, "{}.pop(k, v) doesn't find known key/value pair"
|
||||||
|
|
||||||
d[1] = 1
|
d[1] = 1
|
||||||
try:
|
try:
|
||||||
for i in d:
|
for i in d:
|
||||||
|
@ -139,6 +139,9 @@ class UserDictTest(unittest.TestCase):
|
|||||||
t = UserDict.UserDict(x=42)
|
t = UserDict.UserDict(x=42)
|
||||||
self.assertEqual(t.pop("x"), 42)
|
self.assertEqual(t.pop("x"), 42)
|
||||||
self.assertRaises(KeyError, t.pop, "x")
|
self.assertRaises(KeyError, t.pop, "x")
|
||||||
|
self.assertEqual(t.pop("x", 1), 1)
|
||||||
|
t["x"] = 42
|
||||||
|
self.assertEqual(t.pop("x", 1), 42)
|
||||||
|
|
||||||
# Test popitem
|
# Test popitem
|
||||||
t = UserDict.UserDict(x=42)
|
t = UserDict.UserDict(x=42)
|
||||||
@ -242,6 +245,9 @@ class UserDictMixinTest(unittest.TestCase):
|
|||||||
self.assertEqual(s.pop(10), 'ten')
|
self.assertEqual(s.pop(10), 'ten')
|
||||||
self.assert_(10 not in s)
|
self.assert_(10 not in s)
|
||||||
s[10] = 'ten'
|
s[10] = 'ten'
|
||||||
|
self.assertEqual(s.pop("x", 1), 1)
|
||||||
|
s["x"] = 42
|
||||||
|
self.assertEqual(s.pop("x", 1), 42)
|
||||||
|
|
||||||
# popitem
|
# popitem
|
||||||
k, v = s.popitem()
|
k, v = s.popitem()
|
||||||
|
@ -12,6 +12,12 @@ What's New in Python 2.3 beta 1?
|
|||||||
Core and builtins
|
Core and builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- dict.pop now takes an optional argument specifying a default
|
||||||
|
value to return if the key is not in the dict. If a default is not
|
||||||
|
given and the key is not found, a KeyError will still be raised.
|
||||||
|
Parallel changes were made to UserDict.UserDict and UserDict.DictMixin.
|
||||||
|
[SF patch #693753] (contributed by Michael Stone.)
|
||||||
|
|
||||||
- sys.getfilesystemencoding() was added to expose
|
- sys.getfilesystemencoding() was added to expose
|
||||||
Py_FileSystemDefaultEncoding.
|
Py_FileSystemDefaultEncoding.
|
||||||
|
|
||||||
|
@ -1544,13 +1544,20 @@ dict_clear(register dictobject *mp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
dict_pop(dictobject *mp, PyObject *key)
|
dict_pop(dictobject *mp, PyObject *args)
|
||||||
{
|
{
|
||||||
long hash;
|
long hash;
|
||||||
dictentry *ep;
|
dictentry *ep;
|
||||||
PyObject *old_value, *old_key;
|
PyObject *old_value, *old_key;
|
||||||
|
PyObject *key, *deflt = NULL;
|
||||||
|
|
||||||
|
if(!PyArg_UnpackTuple(args, "pop", 1, 2, &key, &deflt))
|
||||||
|
return NULL;
|
||||||
if (mp->ma_used == 0) {
|
if (mp->ma_used == 0) {
|
||||||
|
if (deflt) {
|
||||||
|
Py_INCREF(deflt);
|
||||||
|
return deflt;
|
||||||
|
}
|
||||||
PyErr_SetString(PyExc_KeyError,
|
PyErr_SetString(PyExc_KeyError,
|
||||||
"pop(): dictionary is empty");
|
"pop(): dictionary is empty");
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1563,6 +1570,10 @@ dict_pop(dictobject *mp, PyObject *key)
|
|||||||
}
|
}
|
||||||
ep = (mp->ma_lookup)(mp, key, hash);
|
ep = (mp->ma_lookup)(mp, key, hash);
|
||||||
if (ep->me_value == NULL) {
|
if (ep->me_value == NULL) {
|
||||||
|
if (deflt) {
|
||||||
|
Py_INCREF(deflt);
|
||||||
|
return deflt;
|
||||||
|
}
|
||||||
PyErr_SetObject(PyExc_KeyError, key);
|
PyErr_SetObject(PyExc_KeyError, key);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1719,7 +1730,8 @@ PyDoc_STRVAR(setdefault_doc__,
|
|||||||
"D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D");
|
"D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D");
|
||||||
|
|
||||||
PyDoc_STRVAR(pop__doc__,
|
PyDoc_STRVAR(pop__doc__,
|
||||||
"D.pop(k) -> v, remove specified key and return the corresponding value");
|
"D.pop(k[,d]) -> v, remove specified key and return the corresponding value\n\
|
||||||
|
If key is not found, d is returned if given, otherwise KeyError is raised");
|
||||||
|
|
||||||
PyDoc_STRVAR(popitem__doc__,
|
PyDoc_STRVAR(popitem__doc__,
|
||||||
"D.popitem() -> (k, v), remove and return some (key, value) pair as a\n\
|
"D.popitem() -> (k, v), remove and return some (key, value) pair as a\n\
|
||||||
@ -1763,7 +1775,7 @@ static PyMethodDef mapp_methods[] = {
|
|||||||
get__doc__},
|
get__doc__},
|
||||||
{"setdefault", (PyCFunction)dict_setdefault, METH_VARARGS,
|
{"setdefault", (PyCFunction)dict_setdefault, METH_VARARGS,
|
||||||
setdefault_doc__},
|
setdefault_doc__},
|
||||||
{"pop", (PyCFunction)dict_pop, METH_O,
|
{"pop", (PyCFunction)dict_pop, METH_VARARGS,
|
||||||
pop__doc__},
|
pop__doc__},
|
||||||
{"popitem", (PyCFunction)dict_popitem, METH_NOARGS,
|
{"popitem", (PyCFunction)dict_popitem, METH_NOARGS,
|
||||||
popitem__doc__},
|
popitem__doc__},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user