Add two dicts

Discussion in 'Python' started by Afanasiy, Aug 29, 2003.

  1. Afanasiy

    Afanasiy Guest

    I have some code like this...

    self.write(
    '''
    lots of stuff here with %(these)s named expressions
    '''
    % vars(self)
    )

    Then I wanted to add an item to the dict vars(self), so I tried :

    vars(self)+{'x':'123','y':'345'}

    This doesn't work, perhaps because no one could decide what should happen
    to keys which already exist in the dict? (I'd say throw an exception).

    Can I add two dicts in a way which is not cumbersome to the above % string
    operation? Is this another case of writing my own function, or does a
    builtin (or similar) already exist for this?
     
    Afanasiy, Aug 29, 2003
    #1
    1. Advertising

  2. Afanasiy

    mackstann Guest

    On Fri, Aug 29, 2003 at 04:11:09AM +0000, Afanasiy wrote:
    [ ... ]
    > Then I wanted to add an item to the dict vars(self), so I tried :
    >
    > vars(self)+{'x':'123','y':'345'}
    >
    > This doesn't work, perhaps because no one could decide what should happen
    > to keys which already exist in the dict? (I'd say throw an exception).
    >
    > Can I add two dicts in a way which is not cumbersome to the above % string
    > operation? Is this another case of writing my own function, or does a
    > builtin (or similar) already exist for this?


    You can use dict.update(), however, this works in place, so you'll have
    to do it outside of the actual string% statement.

    d = {"a": 1, "b": 2}
    d.update({'x':'123','y':'345'})

    print "%(..)s %(..)d ..." % d

    --
    m a c k s t a n n mack @ incise.org http://incise.org
    So, what's with this guy Gideon, anyway?
    And why can't he ever remember his Bible?
     
    mackstann, Aug 29, 2003
    #2
    1. Advertising

  3. Afanasiy wrote:

    > Can I add two dicts in a way which is not cumbersome to the above %
    > string
    > operation? Is this another case of writing my own function, or does a
    > builtin (or similar) already exist for this?


    combinedDict = aDict.copy()
    combinedDict.update(anotherDict)

    If that's cumbersome, don't really know what you'd consider
    non-cumbersome.

    --
    Erik Max Francis && && http://www.alcyone.com/max/
    __ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
    / \ The revolution will not televised
    \__/ Public Enemy
     
    Erik Max Francis, Aug 29, 2003
    #3
  4. Afanasiy

    Afanasiy Guest

    On Thu, 28 Aug 2003 22:07:06 -0700, Erik Max Francis <>
    wrote:

    >Afanasiy wrote:
    >
    >> Can I add two dicts in a way which is not cumbersome to the above %
    >> string
    >> operation? Is this another case of writing my own function, or does a
    >> builtin (or similar) already exist for this?

    >
    > combinedDict = aDict.copy()
    > combinedDict.update(anotherDict)
    >
    >If that's cumbersome, don't really know what you'd consider
    >non-cumbersome.


    Don't really know if you're asking, but :

    vars(self)+{'x':'123','y':'345'}

    I would consider that non-cumbersome. ;-)

    My only guess why that doesn't exist is that no one decided what to do on
    like keys. Use existing, overwrite, or throw exception (my preference).
     
    Afanasiy, Aug 29, 2003
    #4
  5. Afanasiy wrote:

    > On Thu, 28 Aug 2003 22:07:06 -0700, Erik Max Francis <>
    > wrote:
    >
    >>Afanasiy wrote:
    >>
    >>> Can I add two dicts in a way which is not cumbersome to the above %
    >>> string
    >>> operation? Is this another case of writing my own function, or does a
    >>> builtin (or similar) already exist for this?

    >>
    >>combinedDict = aDict.copy()
    >>combinedDict.update(anotherDict)
    >>
    >>If that's cumbersome, don't really know what you'd consider
    >>non-cumbersome.

    >
    > Don't really know if you're asking, but :
    >
    > vars(self)+{'x':'123','y':'345'}
    >
    > I would consider that non-cumbersome. ;-)


    So, what about:

    def dict_add(adict, another):
    result = adict.copy()
    result.update(another)
    return result

    and then dict_add(vars(self), {'x':'123','y':'345'}) ? But in fact
    you can do even better...:

    def dad(_adict, _another={}, **_yetmore):
    result = _adict.copy()
    result.update(_another)
    result.update(_yetmore)
    return result

    or in 2.3:

    def dad(_adict, _another={}, **_yetmore):
    result = _adict.copy()
    result.update(dict(_another, **_yetmore))
    return result


    and now, dad(vars(self), x='123', y='345') -- ain't that even
    LESS cumbersome? You can't do that with the syntax of + (no
    keyword arguments)

    Incidentally, in 2.3 you can ALSO spell your desired
    adict+anotherdict
    as
    dict(adict, **anotherdict)

    > My only guess why that doesn't exist is that no one decided what to do on
    > like keys. Use existing, overwrite, or throw exception (my preference).


    The semantics of all the existing ways of spelling dictionary addition
    and the like (update method, **kwds argument to dict in 2.3) have the
    second argument 'override' the first. A fast way to check that two
    dicts don't overlap (or perhaps more generally to get the list of the
    keys in which they do overlap) might be more generally useful, as well
    as allowing the diagnostics you want to be produced effectively. Still,
    as long as you're writing a function for the addition it's easy and
    fast to check for non-overlap:

    def dad(_adict, _another={}, **_yetmore):
    result = _adict.copy()
    result.update(dict(_another, **_yetmore))
    if len(result)!=len(_adict)+len(_another)+len(_yetmore):
    raise ValueError, "Overlapping keys on dict addition"
    return result


    Alex
     
    Alex Martelli, Aug 29, 2003
    #5
  6. Afanasiy wrote:

    > I have some code like this...
    >
    > self.write(
    > '''
    > lots of stuff here with %(these)s named expressions
    > '''
    > % vars(self)
    > )
    >
    > Then I wanted to add an item to the dict vars(self), so I tried :
    >
    > vars(self)+{'x':'123','y':'345'}
    >
    > This doesn't work, perhaps because no one could decide what should happen
    > to keys which already exist in the dict? (I'd say throw an exception).
    >
    > Can I add two dicts in a way which is not cumbersome to the above % string
    > operation? Is this another case of writing my own function, or does a
    > builtin (or similar) already exist for this?


    In Python 2.3, you can, if you wish, code:

    self.write(
    '''
    lots of stuff here with %(these)s named expressions
    '''
    % dict(vars(self), x='123', y='345')
    )

    thanks to the new feature of dict of allowing a **kwds argument (with
    the 'obvious' semantics, however: named keys override keys already
    present in the first argument -- if you need to diagnose overlap and
    raise an exception thereupon, you'll have to do that separately).

    More generally, if you had an existing dict D you wanted to "add" to
    vars(self), rather than a literal, you could code:

    self.write(
    '''
    lots of stuff here with %(these)s named expressions
    '''
    % dict(vars(self), **D)
    )


    Alex
     
    Alex Martelli, Aug 29, 2003
    #6
  7. Afanasiy <> wrote in message news:<>...
    > I have some code like this...
    >
    > self.write(
    > '''
    > lots of stuff here with %(these)s named expressions
    > '''
    > % vars(self)
    > )
    >
    > Then I wanted to add an item to the dict vars(self), so I tried :
    >
    > vars(self)+{'x':'123','y':'345'}
    >
    > This doesn't work, perhaps because no one could decide what should happen
    > to keys which already exist in the dict? (I'd say throw an exception).
    >
    > Can I add two dicts in a way which is not cumbersome to the above % string
    > operation? Is this another case of writing my own function, or does a
    > builtin (or similar) already exist for this?


    Here is a possibile solution:

    class attributes(dict):
    def __init__(self,obj):
    if isinstance(obj,dict):
    self.update(obj)
    elif hasattr(obj,'__dict__'):
    self.update(obj.__dict__)
    else:
    raise TypeError("Dictionary or object with a __dict__ required")
    def __add__(self,other):
    self.update(other)
    return self.__class__(self)
    __radd__=__add__

    class C(object):
    def __init__(self,x,y):
    self.x=x
    self.y=y


    c=C(1,2)
    print attributes(c)
    print attributes(c)+{'z':3}
    print {'z':3}+attributes(c)


    Michele Simionato, Ph. D.

    http://www.phyast.pitt.edu/~micheles
    --- Currently looking for a job ---

    http://www.strakt.com/dev_talks.html

    http://www.ibm.com/developerworks/library/l-pymeta2/?ca=dnt-434
     
    Michele Simionato, Aug 29, 2003
    #7
  8. On 29 Aug 2003 05:40:15 -0700, rumours say that (Michele
    Simionato) might have written:

    [snip]

    > def __add__(self,other):
    > self.update(other)
    > return self.__class__(self)


    hm... I am not sure about this; it's not iadd, so you shouldn't modify
    self.

    Perhaps you should (untested):
    def __add__(self, other):
    temp = self.copy()
    temp.update(other)
    return temp
    --
    TZOTZIOY, I speak England very best,
    Microsoft Security Alert: the Matrix began as open source.
     
    Christos TZOTZIOY Georgiou, Aug 29, 2003
    #8
  9. Christos "TZOTZIOY" Georgiou <> wrote in message news:<>...
    > On 29 Aug 2003 05:40:15 -0700, rumours say that (Michele
    > Simionato) might have written:
    >
    > [snip]
    >
    > > def __add__(self,other):
    > > self.update(other)
    > > return self.__class__(self)

    >
    > hm... I am not sure about this; it's not iadd, so you shouldn't modify
    > self.
    >
    > Perhaps you should (untested):
    > def __add__(self, other):
    > temp = self.copy()
    > temp.update(other)
    > return temp


    As you wish ;)

    Michele Simionato, Ph. D.

    http://www.phyast.pitt.edu/~micheles
    --- Currently looking for a job ---
     
    Michele Simionato, Aug 29, 2003
    #9
  10. Afanasiy

    Greg Brunet Guest

    "Alex Martelli" <> wrote in message
    news:BjE3b.7850$...
    > Afanasiy wrote:
    >
    > > On Thu, 28 Aug 2003 22:07:06 -0700, Erik Max Francis

    <>
    > > wrote:
    > >
    > >>Afanasiy wrote:
    > >>
    > >>> Can I add two dicts in a way which is not cumbersome to the above

    %
    > >>> string
    > >>> operation? Is this another case of writing my own function, or

    does a
    > >>> builtin (or similar) already exist for this?
    > >>
    > >>combinedDict = aDict.copy()
    > >>combinedDict.update(anotherDict)
    > >>
    > >>If that's cumbersome, don't really know what you'd consider
    > >>non-cumbersome.

    > >
    > > Don't really know if you're asking, but :
    > >
    > > vars(self)+{'x':'123','y':'345'}
    > >
    > > I would consider that non-cumbersome. ;-)

    >
    > So, what about:
    >
    > def dict_add(adict, another):
    > result = adict.copy()
    > result.update(another)
    > return result
    >
    > and then dict_add(vars(self), {'x':'123','y':'345'}) ? But in fact
    > you can do even better...:
    >

    .... lots of other good ideas...

    But what about something like this:

    >>> class xdict(dict):

    .... def __add__(self,dict2):
    .... result = self.copy()
    .... result = result.update(dict2)
    ....

    I was hoping that would allow:
    >>> a=xdict({'y': 456, 'x': 111})
    >>> b=xdict({'y': 444, 'z': 789})
    >>> a+b


    but instead of the result which I hoped for, I get the following:

    Traceback (most recent call last):
    File "<interactive input>", line 1, in ?
    TypeError: unsupported operand type(s) for +: 'xdict' and 'xdict'

    So I can't implement '+' operator for dictionaries - why not?

    --
    Greg
     
    Greg Brunet, Aug 30, 2003
    #10
  11. Afanasiy

    Greg Brunet Guest

    "Greg Brunet" <> wrote in message
    news:...
    > But what about something like this:
    >
    > >>> class xdict(dict):

    > ... def __add__(self,dict2):
    > ... result = self.copy()
    > ... result = result.update(dict2)
    > ...
    >
    > I was hoping that would allow:
    > >>> a=xdict({'y': 456, 'x': 111})
    > >>> b=xdict({'y': 444, 'z': 789})
    > >>> a+b

    >
    > but instead of the result which I hoped for, I get the following:
    >
    > Traceback (most recent call last):
    > File "<interactive input>", line 1, in ?
    > TypeError: unsupported operand type(s) for +: 'xdict' and 'xdict'
    >
    > So I can't implement '+' operator for dictionaries - why not?



    Ooops - that should have been:
    return result.update(dict2)

    in the last line, but still, shouldn't that have mapped the "+" operator
    for xdict objects?

    --
    Greg
     
    Greg Brunet, Aug 30, 2003
    #11
  12. Afanasiy

    Greg Brunet Guest

    "Greg Brunet" <> wrote in message
    news:...
    > "Greg Brunet" <> wrote in message
    > news:...
    > > But what about something like this:
    > >
    > > >>> class xdict(dict):

    > > ... def __add__(self,dict2):
    > > ... result = self.copy()
    > > ... result = result.update(dict2)


    .... I was getting sloppy in the interactive mode. Instead I did this &
    it seems to work properly:


    class xdict(dict):
    def add(self,dict2):
    result = self.copy()
    result.update(dict2)
    return result

    def __add__(self,dict2):
    result = self.copy()
    result.update(dict2)
    return result

    def __iadd__(self,dict2):
    self.update(dict2)
    return self

    a=xdict({'x':1})
    b=xdict({'y':2})
    print
    print "Add:", a.add(b)
    print "+:", a+b
    print "a:",a,"b:",b
    a+=b
    print "+= (a=):", a

    Results:
    Add: {'y': 2, 'x': 1}
    +: {'y': 2, 'x': 1}
    a: {'x': 1} b: {'y': 2}
    += (a=): {'y': 2, 'x': 1}


    --
    Greg
     
    Greg Brunet, Aug 30, 2003
    #12
  13. Afanasiy

    John Roth Guest

    "Greg Brunet" <> wrote in message
    news:...
    > "Alex Martelli" <> wrote in message
    > news:BjE3b.7850$...
    > > Afanasiy wrote:
    > >
    > > > On Thu, 28 Aug 2003 22:07:06 -0700, Erik Max Francis

    > <>
    > > > wrote:
    > > >
    > > >>Afanasiy wrote:
    > > >>
    > > >>> Can I add two dicts in a way which is not cumbersome to the above

    > %
    > > >>> string
    > > >>> operation? Is this another case of writing my own function, or

    > does a
    > > >>> builtin (or similar) already exist for this?
    > > >>
    > > >>combinedDict = aDict.copy()
    > > >>combinedDict.update(anotherDict)
    > > >>
    > > >>If that's cumbersome, don't really know what you'd consider
    > > >>non-cumbersome.
    > > >
    > > > Don't really know if you're asking, but :
    > > >
    > > > vars(self)+{'x':'123','y':'345'}
    > > >
    > > > I would consider that non-cumbersome. ;-)

    > >
    > > So, what about:
    > >
    > > def dict_add(adict, another):
    > > result = adict.copy()
    > > result.update(another)
    > > return result
    > >
    > > and then dict_add(vars(self), {'x':'123','y':'345'}) ? But in fact
    > > you can do even better...:
    > >

    > ... lots of other good ideas...
    >
    > But what about something like this:
    >
    > >>> class xdict(dict):

    > ... def __add__(self,dict2):
    > ... result = self.copy()
    > ... result = result.update(dict2)
    > ...
    >
    > I was hoping that would allow:
    > >>> a=xdict({'y': 456, 'x': 111})
    > >>> b=xdict({'y': 444, 'z': 789})
    > >>> a+b

    >
    > but instead of the result which I hoped for, I get the following:
    >
    > Traceback (most recent call last):
    > File "<interactive input>", line 1, in ?
    > TypeError: unsupported operand type(s) for +: 'xdict' and 'xdict'
    >
    > So I can't implement '+' operator for dictionaries - why not?


    The special functions can only be defined in the class
    definition. They cannot be added afterwards. This is a
    compiler optimization to avoid having to do dictionary
    lookups on every operator.

    If you want to do this, subclass dict.

    John Roth
    >
    > --
    > Greg
    >
    >
    >
     
    John Roth, Aug 30, 2003
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jiba

    unicode keys in dicts

    Jiba, Jan 8, 2004, in forum: Python
    Replies:
    2
    Views:
    328
    Peter Hansen
    Jan 8, 2004
  2. Charlie

    classes vs dicts

    Charlie, May 6, 2004, in forum: Python
    Replies:
    24
    Views:
    727
    David MacQuigg
    May 18, 2004
  3. J
    Replies:
    4
    Views:
    307
    Chris Rebert
    Jul 19, 2011
  4. bruce
    Replies:
    0
    Views:
    277
    bruce
    Jan 10, 2012
  5. Roy Smith

    Deep merge two dicts?

    Roy Smith, Apr 12, 2012, in forum: Python
    Replies:
    2
    Views:
    714
Loading...

Share This Page