Add two dicts

A

Afanasiy

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?
 
M

mackstann

]
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
 
E

Erik Max Francis

Afanasiy said:
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.
 
A

Afanasiy

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).
 
A

Alex Martelli

Afanasiy said:
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
 
A

Alex Martelli

Afanasiy said:
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
 
M

Michele Simionato

Afanasiy said:
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.
(e-mail address removed)
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
 
C

Christos TZOTZIOY Georgiou

On 29 Aug 2003 05:40:15 -0700, rumours say that (e-mail address removed) (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
 
M

Michele Simionato

Christos "TZOTZIOY" Georgiou said:
On 29 Aug 2003 05:40:15 -0700, rumours say that (e-mail address removed) (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.
(e-mail address removed)
http://www.phyast.pitt.edu/~micheles
--- Currently looking for a job ---
 
G

Greg Brunet

Alex Martelli said:
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:
.... def __add__(self,dict2):
.... result = self.copy()
.... result = result.update(dict2)
....

I was hoping that would allow:
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?
 
G

Greg Brunet

Greg Brunet said:
But what about something like this:

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

I was hoping that would allow:

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?
 
G

Greg Brunet

.... 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}
 
J

John Roth

Greg Brunet said:
... lots of other good ideas...

But what about something like this:

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

I was hoping that would allow:

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,906
Latest member
SkinfixSkintag

Latest Threads

Top