]> granicus.if.org Git - python/commitdiff
Optimize dict.fromkeys() with dict inputs. Useful for resetting bag/muliset counts...
authorRaymond Hettinger <python@rcn.com>
Wed, 7 Nov 2007 02:26:17 +0000 (02:26 +0000)
committerRaymond Hettinger <python@rcn.com>
Wed, 7 Nov 2007 02:26:17 +0000 (02:26 +0000)
Lib/test/test_dict.py
Objects/dictobject.c

index 7f0aabb20a86fbaa206bce2aa109af9eb1eff5bc..9f049ad41a17b4d13608dae6d13d399d2e4f7eee 100644 (file)
@@ -243,6 +243,10 @@ class DictTest(unittest.TestCase):
 
         self.assertRaises(Exc, baddict2.fromkeys, [1])
 
+        # test fast path for dictionary inputs
+        d = dict(zip(range(6), range(6)))
+        self.assertEqual(dict.fromkeys(d, 0), dict(zip(range(6), [0]*6)))
+
     def test_copy(self):
         d = {1:1, 2:2, 3:3}
         self.assertEqual(d.copy(), {1:1, 2:2, 3:3})
index 9b99bbf46e9dfe711b009d0bd674745e15d35e46..00f9bc8b2fa100cab1faa273f4ac90f2c2998b89 100644 (file)
@@ -1184,6 +1184,25 @@ dict_fromkeys(PyObject *cls, PyObject *args)
        if (d == NULL)
                return NULL;
 
+       if (PyDict_CheckExact(d) && PyDict_CheckExact(seq)) {
+               PyDictObject *mp = (PyDictObject *)d;
+               PyObject *oldvalue;
+               Py_ssize_t pos = 0;
+               PyObject *key;
+               long hash;
+
+               if (dictresize(mp, ((PyDictObject *)seq)->ma_used))
+                       return NULL;
+
+               while (_PyDict_Next(seq, &pos, &key, &oldvalue, &hash)) {
+                       Py_INCREF(key);
+                       Py_INCREF(value);
+                       if (insertdict(mp, key, hash, value))
+                               return NULL;
+               }
+               return d;
+       }
+
        if (PyDict_CheckExact(d) && PyAnySet_CheckExact(seq)) {
                PyDictObject *mp = (PyDictObject *)d;
                Py_ssize_t pos = 0;