]> granicus.if.org Git - python/commitdiff
SF Patch 643443. Added dict.fromkeys(iterable, value=None), a class
authorRaymond Hettinger <python@rcn.com>
Wed, 27 Nov 2002 07:29:33 +0000 (07:29 +0000)
committerRaymond Hettinger <python@rcn.com>
Wed, 27 Nov 2002 07:29:33 +0000 (07:29 +0000)
method for constructing new dictionaries from sequences of keys.

Doc/lib/libstdtypes.tex
Lib/test/test_types.py
Misc/NEWS
Objects/dictobject.c

index eb12aa7f44f8f4f402eea72438787d0dc096fd4c..6f9e4533702df38216caf582d3ed952e41ae0d9f 100644 (file)
@@ -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}}
index c20af2e6f383cbee0812dd1c98c7c57fa9570b54..9cfc6806adb4e3bb91b502a5c294576f54d0dd4d 100644 (file)
@@ -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'
index 89303ba9f8ddbc86f587b062224cd5654a70c5eb..066f8a5b3676ace7974164eddde355d5eb6ad615 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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]
 
index 2eaa20c26da83399b52057d036d2bdb4cca6685a..b8ba7e15d706fe2012c079298cb1f95527330916 100644 (file)
@@ -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,