On 06/07/2010 10:17 PM, kkumer wrote: > I have to merge two dictionaries into one, and in > a "shallow" way: changing items should be possible > by operating either on two parents or on a > new dictionary. I am open to suggestions how > to do this (values are always numbers, BTW), but > I tried to do it by creating a dict-like class that just > forwards all calls to the two parent dicts, see below. > > It works, but one important thing is missing. I > am not able to expand new dictionary with > double-star operator ** to use it as a > set of keyword arguments of a function. > I googled a bit, but was unable to find what > property must an object have to be correctly > treated by **. > My guess would be that this only works with dicts, and uses the internal representation of the dict, not the python-defined methods. I don't know what you want to do, but you might be better off creating a special "mergeabledict" type for the parents, and then allow them to connect, actually copying all items over. Though it might be best just to use one single dict ;-)
> I hope the following code is self-explanatory: > > ------------------------------------ > > import itertools > > class hubDict(dict): > """Merges two dictionaries, but not actually but just by forwarding.""" > > def __init__(self, da, db): > self.d1 = da > self.d2 = db > > def __getitem__(self, name): > if self.d1.has_key(name): > return self.d1[name] > else: > return self.d2[name] > > def __setitem__(self, name, value): > if self.d1.has_key(name): > self.d1[name] = value > else: > self.d2[name] = value > > def __iter__(self): > return itertools.chain(self.d1.__iter__(), self.d2.__iter__()) > > def has_key(self, name): > if self.d1.has_key(name) or self.d2.has_key(name): > return True > else: > return False > > def keys(self): > return self.d1.keys() + self.d2.keys() > > def items(self): > return self.d1.items() + self.d2.items() > > def iteritems(self): > return itertools.chain(self.d1.iteritems(), self.d2.iteritems()) > > def iterkeys(self): > return itertools.chain(self.d1.iterkeys(), self.d2.iterkeys()) > > def itervalues(self): > return itertools.chain(self.d1.itervalues(), self.d2.itervalues()) > > def copy(self): > print "Can't copy hubDict yet!!!" > > def update(self, d): > for key in d: > self.__setitem__(key, d[key]) > > def popitem(self): > try: > return self.d1.popitem() > except KeyError: > return self.d2.popitem() > > def __repr__(self): > return 'First: %s\nSecond: %s' % ( > self.d1.__repr__(), self.d2.__repr__()) > > > # Trying it now: > > da = {'a':1} > db = {'b':2} > dh = hubDict(da, db) > def kwa(**kwargs): print kwargs > > #OK > kwa(**da) > > #not OK: prints empty dict > kwa(**dh) > > > import itertools > > class hubDict(dict): > """Merges two dictionaries, but not actually but just by forwarding.""" > > def __init__(self, da, db): > self.d1 = da > self.d2 = db > > def __getitem__(self, name): > if self.d1.has_key(name): > return self.d1[name] > else: > return self.d2[name] > > def __setitem__(self, name, value): > if self.d1.has_key(name): > self.d1[name] = value > else: > self.d2[name] = value > > def __iter__(self): > return itertools.chain(self.d1.__iter__(), self.d2.__iter__()) > > def has_key(self, name): > if self.d1.has_key(name) or self.d2.has_key(name): > return True > else: > return False > > def keys(self): > return self.d1.keys() + self.d2.keys() > > def items(self): > return self.d1.items() + self.d2.items() > > def iteritems(self): > return itertools.chain(self.d1.iteritems(), self.d2.iteritems()) > > def iterkeys(self): > return itertools.chain(self.d1.iterkeys(), self.d2.iterkeys()) > > def itervalues(self): > return itertools.chain(self.d1.itervalues(), self.d2.itervalues()) > > def copy(self): > print "Can't copy hubDict yet!!!" > > def update(self, d): > for key in d: > self.__setitem__(key, d[key]) > > def popitem(self): > try: > return self.d1.popitem() > except KeyError: > return self.d2.popitem() > > def __repr__(self): > return 'First: %s\nSecond: %s' % ( > self.d1.__repr__(), self.d2.__repr__()) > > def __len__(self): > return self.d1.__len__() + self.d2.__len__() > > # Trying it now: > > da = {'a':1} > db = {'b':2} > dh = hubDict(da, db) > def kwa(**kwargs): print kwargs > > #OK > kwa(**da) > > #not OK: prints empty dict > kwa(**dh) > > -- http://mail.python.org/mailman/listinfo/python-list