mirror of
https://github.com/python/cpython.git
synced 2025-10-17 12:18:23 +00:00
SF Patch 643443. Added dict.fromkeys(iterable, value=None), a class
method for constructing new dictionaries from sequences of keys.
This commit is contained in:
parent
e9cfcef71e
commit
e33d3df030
4 changed files with 97 additions and 1 deletions
|
@ -1055,8 +1055,11 @@ arbitrary objects):
|
|||
{(3)}
|
||||
\lineiii{\var{a}.keys()}{a copy of \var{a}'s list of keys}{(3)}
|
||||
\lineiii{\var{a}.update(\var{b})}
|
||||
{\code{for k in \var{b}.keys(): \var{a}[k] = \var{b}[k]}}
|
||||
{\code{for \var{k} in \var{b}.keys(): \var{a}[\var{k}] = \var{b}[\var{k}]}}
|
||||
{}
|
||||
\lineiii{\var{a}.fromkeys(\var{seq}\optional{, \var{value}})}
|
||||
{Creates a new dictionary with keys from \var{seq} and values set to \var{value}}
|
||||
{(7)}
|
||||
\lineiii{\var{a}.values()}{a copy of \var{a}'s list of values}{(3)}
|
||||
\lineiii{\var{a}.get(\var{k}\optional{, \var{x}})}
|
||||
{\code{\var{a}[\var{k}]} if \code{\var{k} in \var{a}},
|
||||
|
@ -1116,6 +1119,10 @@ the dictionary as the value of \var{k}.
|
|||
over a dictionary, as often used in set algorithms.
|
||||
\end{description}
|
||||
|
||||
\item[(7)] \function{fromkeys()} is a class method that returns a
|
||||
new dictionary. \var{value} defaults to \code{None}. \versionadded{2.3}
|
||||
\end{description}
|
||||
|
||||
|
||||
\subsection{File Objects
|
||||
\label{bltin-file-objects}}
|
||||
|
|
|
@ -530,6 +530,34 @@ class FailingUserDict:
|
|||
try: d.update(FailingUserDict())
|
||||
except ValueError: pass
|
||||
else: raise TestFailed, 'dict.update(), __getitem__ expected ValueError'
|
||||
# dict.fromkeys()
|
||||
if dict.fromkeys('abc') != {'a':None, 'b':None, 'c':None}:
|
||||
raise TestFailed, 'dict.fromkeys did not work as a class method'
|
||||
d = {}
|
||||
if d.fromkeys('abc') is d:
|
||||
raise TestFailed, 'dict.fromkeys did not return a new dict'
|
||||
if d.fromkeys('abc') != {'a':None, 'b':None, 'c':None}:
|
||||
raise TestFailed, 'dict.fromkeys failed with default value'
|
||||
if d.fromkeys((4,5),0) != {4:0, 5:0}:
|
||||
raise TestFailed, 'dict.fromkeys failed with specified value'
|
||||
if d.fromkeys([]) != {}:
|
||||
raise TestFailed, 'dict.fromkeys failed with null sequence'
|
||||
def g():
|
||||
yield 1
|
||||
if d.fromkeys(g()) != {1:None}:
|
||||
raise TestFailed, 'dict.fromkeys failed with a generator'
|
||||
try: {}.fromkeys(3)
|
||||
except TypeError: pass
|
||||
else: raise TestFailed, 'dict.fromkeys failed to raise TypeError'
|
||||
class dictlike(dict): pass
|
||||
if dictlike.fromkeys('a') != {'a':None}:
|
||||
raise TestFailed, 'dictsubclass.fromkeys did not inherit'
|
||||
if dictlike().fromkeys('a') != {'a':None}:
|
||||
raise TestFailed, 'dictsubclass.fromkeys did not inherit'
|
||||
if type(dictlike.fromkeys('a')) is not dictlike:
|
||||
raise TestFailed, 'dictsubclass.fromkeys created wrong type'
|
||||
if type(dictlike().fromkeys('a')) is not dictlike:
|
||||
raise TestFailed, 'dictsubclass.fromkeys created wrong type'
|
||||
# dict.copy()
|
||||
d = {1:1, 2:2, 3:3}
|
||||
if d.copy() != {1:1, 2:2, 3:3}: raise TestFailed, 'dict copy'
|
||||
|
|
|
@ -270,6 +270,11 @@ Core and builtins
|
|||
an optional argument that specifies the characters to strip. For
|
||||
example, "Foo!!!?!?!?".rstrip("?!") -> "Foo".
|
||||
|
||||
- Dictionaries have a new class method, fromkeys(iterable, value=None).
|
||||
It constructs a new dictionary with keys taken from the iterable and
|
||||
all values set to a single value. It is used for building membership
|
||||
tests and for removing duplicates from sequences.
|
||||
|
||||
- Added a new dict method pop(key). This removes and returns the
|
||||
value corresponding to key. [SF patch #539949]
|
||||
|
||||
|
|
|
@ -962,6 +962,56 @@ dict_items(register dictobject *mp)
|
|||
return v;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
dict_fromkeys(PyObject *mp, PyObject *args)
|
||||
{
|
||||
PyObject *seq;
|
||||
PyObject *value = Py_None;
|
||||
PyObject *it; /* iter(seq) */
|
||||
PyObject *key;
|
||||
PyObject *d;
|
||||
PyObject *cls;
|
||||
int status;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "OO|O:fromkeys", &cls, &seq, &value))
|
||||
return NULL;
|
||||
|
||||
d = PyObject_CallObject(cls, NULL);
|
||||
if (d == NULL)
|
||||
return NULL;
|
||||
if (!PyDict_Check(d)) {
|
||||
PyErr_BadInternalCall();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
it = PyObject_GetIter(seq);
|
||||
if (it == NULL){
|
||||
Py_DECREF(d);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
key = PyIter_Next(it);
|
||||
if (key == NULL) {
|
||||
if (PyErr_Occurred())
|
||||
goto Fail;
|
||||
break;
|
||||
}
|
||||
status = PyDict_SetItem(d, key, value);
|
||||
Py_DECREF(key);
|
||||
if (status < 0)
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
Py_DECREF(it);
|
||||
return d;
|
||||
|
||||
Fail:
|
||||
Py_DECREF(it);
|
||||
Py_DECREF(d);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
dict_update(PyObject *mp, PyObject *other)
|
||||
{
|
||||
|
@ -1682,6 +1732,10 @@ PyDoc_STRVAR(values__doc__,
|
|||
PyDoc_STRVAR(update__doc__,
|
||||
"D.update(E) -> None. Update D from E: for k in E.keys(): D[k] = E[k]");
|
||||
|
||||
PyDoc_STRVAR(fromkeys__doc__,
|
||||
"dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v.\n\
|
||||
v defaults to None.");
|
||||
|
||||
PyDoc_STRVAR(clear__doc__,
|
||||
"D.clear() -> None. Remove all items from D.");
|
||||
|
||||
|
@ -1716,6 +1770,8 @@ static PyMethodDef mapp_methods[] = {
|
|||
values__doc__},
|
||||
{"update", (PyCFunction)dict_update, METH_O,
|
||||
update__doc__},
|
||||
{"fromkeys", (PyCFunction)dict_fromkeys, METH_VARARGS | METH_CLASS,
|
||||
fromkeys__doc__},
|
||||
{"clear", (PyCFunction)dict_clear, METH_NOARGS,
|
||||
clear__doc__},
|
||||
{"copy", (PyCFunction)dict_copy, METH_NOARGS,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue