Which objects are expanded by double-star ** operator?

kkumer kkumer at best-search-engines-mail.com
Mon Jun 7 16:17:40 EDT 2010


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 **.

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