[Python-Dev] Re: [Patches] [1.6] dictionary objects: new method 'supplement'

Greg Stein gstein@lyra.org
Mon, 3 Apr 2000 03:18:30 -0700 (PDT)


I don't recall the termination of the discussion, but I don't know that
consensus was ever reached.

Personally, I find this of little value over the similar (not exact) code:

def supplement(dict, extra):
  d = extra.copy()
  d.update(dict)
  return d

If the dictionary needs to be modified in place, then the loop from your
UserDict.supplement would be used.

Another view: why keep adding methods to service all possible needs?

Cheers,
-g

On Mon, 3 Apr 2000, Peter Funk wrote:
> Dear Python patcher!
> 
> Please consider to apply the patch appended below and commit into the CVS tree.
> It applies to: Python 1.6a1 as released on april 1st.
> --=-- argument: --=--=--=--=--=--=--=--=--=--=-->8--=-
> This patch adds a new method to dictionary and UserDict objects:
> '.supplement()' is a "sibling" of '.update()', but it add only
> those items that are not already there instead of replacing them.
> 
> This idea has been discussed on python-dev last month.
> --=-- obligatory disclaimer: -=--=--=--=--=--=-->8--=-
> I confirm that, to the best of my knowledge and belief, this
> contribution is free of any claims of third parties under
> copyright, patent or other rights or interests ("claims").  To
> the extent that I have any such claims, I hereby grant to CNRI a
> nonexclusive, irrevocable, royalty-free, worldwide license to
> reproduce, distribute, perform and/or display publicly, prepare
> derivative versions, and otherwise use this contribution as part
> of the Python software and its related documentation, or any
> derivative versions thereof, at no cost to CNRI or its licensed
> users, and to authorize others to do so.
> 
> I acknowledge that CNRI may, at its sole discretion, decide
> whether or not to incorporate this contribution in the Python
> software and its related documentation.  I further grant CNRI
> permission to use my name and other identifying information
> provided to CNRI by me for use in connection with the Python
> software and its related documentation.
> --=-- dry signature: =--=--=--=--=--=--=--=--=-->8--=-
> Regards, Peter
> -- 
> Peter Funk, Oldenburger Str.86, D-27777 Ganderkesee, Germany, Fax:+49 4222950260
> office: +49 421 20419-0 (ArtCom GmbH, Grazer Str.8, D-28359 Bremen)
> --=-- patch: --=--=--=--=--=--=--=--=--=--=--=-->8--=-
> *** ../../cvs_01_04_00_orig/dist/src/Objects/dictobject.c	Fri Mar 31 11:45:02 2000
> --- src/Objects/dictobject.c	Mon Apr  3 10:30:11 2000
> ***************
> *** 734,739 ****
> --- 734,781 ----
>   }
>   
>   static PyObject *
> + dict_supplement(mp, args)
> +       register dictobject *mp;
> +       PyObject *args;
> + {
> + 	register int i;
> + 	dictobject *other;
> +         dictentry *entry, *oldentry;
> + 	if (!PyArg_Parse(args, "O!", &PyDict_Type, &other))
> + 		return NULL;
> + 	if (other == mp)
> + 		goto done; /* a.supplement(a); nothing to do */
> + 	/* Do one big resize at the start, rather than incrementally
> + 	   resizing as we insert new items.  Expect that there will be
> + 	   no (or few) overlapping keys. */
> + 	if ((mp->ma_fill + other->ma_used)*3 >= mp->ma_size*2) {
> + 		if (dictresize(mp, (mp->ma_used + other->ma_used)*3/2) != 0)
> + 			return NULL;
> + 	}
> + 	for (i = 0; i < other->ma_size; i++) {
> + 		entry = &other->ma_table[i];
> + 		if (entry->me_value != NULL) {
> + 			oldentry = lookdict(mp, entry->me_key, entry->me_hash);
> + 			if (oldentry->me_value == NULL) {
> + 				/* TODO: optimize:
> + 				   'insertdict' does another call to 'lookdict'.
> + 				   But for sake of readability and symmetry with
> + 				   'dict_update' I didn't tried to avoid this.
> + 				   At least not now as we go into 1.6 alpha. */
> + 				Py_INCREF(entry->me_key);
> + 				Py_INCREF(entry->me_value);
> + 				insertdict(mp, entry->me_key, entry->me_hash,
> + 					   entry->me_value);
> + 			}
> + 		}
> + 	}
> +   done:
> + 	Py_INCREF(Py_None);
> + 	return Py_None;
> + }
> + 
> + 
> + static PyObject *
>   dict_copy(mp, args)
>         register dictobject *mp;
>         PyObject *args;
> ***************
> *** 1045,1050 ****
> --- 1087,1093 ----
>   	{"clear",	(PyCFunction)dict_clear},
>   	{"copy",	(PyCFunction)dict_copy},
>   	{"get",         (PyCFunction)dict_get,          METH_VARARGS},
> + 	{"supplement",	(PyCFunction)dict_supplement},
>   	{NULL,		NULL}		/* sentinel */
>   };
>   
> *** ../../cvs_01_04_00_orig/dist/src/Lib/test/test_types.py	Wed Feb 23 23:23:17 2000
> --- src/Lib/test/test_types.py	Mon Apr  3 10:41:53 2000
> ***************
> *** 242,247 ****
> --- 242,250 ----
>   d.update({2:20})
>   d.update({1:1, 2:2, 3:3})
>   if d != {1:1, 2:2, 3:3}: raise TestFailed, 'dict update'
> + d.supplement({1:"not", 2:"neither", 4:4})
> + if d != {1:1, 2:2, 3:3, 4:4}: raise TestFailed, 'dict supplement'
> + del d[4]
>   if d.copy() != {1:1, 2:2, 3:3}: raise TestFailed, 'dict copy'
>   if {}.copy() != {}: raise TestFailed, 'empty dict copy'
>   # dict.get()
> *** ../../cvs_01_04_00_orig/dist/src/Lib/UserDict.py	Wed Feb  2 16:10:14 2000
> --- src/Lib/UserDict.py	Mon Apr  3 10:45:17 2000
> ***************
> *** 32,36 ****
> --- 32,45 ----
>           else:
>               for k, v in dict.items():
>                   self.data[k] = v
> +     def supplement(self, dict):
> +         if isinstance(dict, UserDict):
> +             self.data.supplement(dict.data)
> +         elif isinstance(dict, type(self.data)):
> +             self.data.supplement(dict)
> +         else:
> +             for k, v in dict.items():
> + 		if not self.data.has_key(k):
> + 		    self.data[k] = v
>       def get(self, key, failobj=None):
>           return self.data.get(key, failobj)
> *** ../../cvs_01_04_00_orig/dist/src/Lib/test/test_userdict.py	Fri Mar 26 16:32:02 1999
> --- src/Lib/test/test_userdict.py	Mon Apr  3 10:50:29 2000
> ***************
> *** 93,101 ****
> --- 93,109 ----
>   t.update(u2)
>   assert t == u2
>   
> + # Test supplement
> + 
> + t = UserDict(d1)
> + t.supplement(u2)
> + assert t == u2
> + 
>   # Test get
>   
>   for i in u2.keys():
>       assert u2.get(i) == u2[i]
>       assert u1.get(i) == d1.get(i)
>       assert u0.get(i) == d0.get(i)
> + 
> + # TODO: Add a test using dir({}) to test for unimplemented methods
> 
> _______________________________________________
> Patches mailing list
> Patches@python.org
> http://www.python.org/mailman/listinfo/patches
> 

-- 
Greg Stein, http://www.lyra.org/