Which objects are expanded by double-star ** operator?
Thomas Jollans
thomas at jollans.com
Mon Jun 7 16:33:30 EDT 2010
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)
>
>
More information about the Python-list
mailing list