Colin Corr said unto the world upon 2005-03-16 01:38:
Greetings Tutors,

I am having some difficulties with the concept of functions which can
accept an unnamed number of arguments. Specifically, when trying to
write a function that deals with an unnamed number of dictionaries. I
want to be able to merge any number of dictionaries, while preserving
the values (ie. cannot use update()).


~I would appreciate any help that can point in me in the right
direction, without directly providing me the answer.~

I understand how to accomplish this task with named arguments:

def mergedicts(firstdict, seconddict):
'''merges two dictionaries into a single dictionary, and converts
duplicate key values to a list'''
newdict = firstdict.copy()
for key in seconddict.keys():
if key in firstdict.keys():
newdict[key] = firstdict[key], seconddict[key]
newdict[key] = list(newdict[key])
else:
newdict[key] = seconddict[key]
return newdict



dict1 = {'1':'a','2':'b','3':'c'} dict2 = {'4':'d','5':'e','6':'f','1':'g'} somedicts1 = mergedicts(dict1,dict2) print somedicts1

#returns: {'1': ['a', 'g'], '3': 'c', '2': 'b', '5': 'e', '4': 'd', '6':
'f'}

I also think I understand how to use unnamed arguments to merge lists:

def mergelists(*somelists):
'''merges multiple lists into a single list and consolidates lists
elements'''
mergedict = {}
for element in somelists:
for unique in element:
mergedict[unique] = 1
combolist = mergedict.keys()
return combolist
Where I am getting hung up is that, if I do this with unnamed arguments
for dictionaries:


def mergedicts(*somedicts):

I get an: AttributeError: 'tuple' object has no attribute 'keys'


However, I run into the same problem when trying with one named, and unnamed.

def mergedicts2(firstdict,*somedicts):
    '''merges any number of dictionaries into a single dictionary, and
converts duplicate key values to a list'''
    merged = firstdict.copy()
    for key in somedicts.keys():
        if key in merged.keys():
            merged[key] = merged[key], somedicts[key]
            merged[key] = list(merged[key])
        else:
            merged[key] = somedicts[key]

    return merged

Based on my understanding of how unnamed arguments work in functions: I
think the dictionaries are being converted into a tuple of all of the
dictionary values, and I cannot make a working copy of the first
dictionary passed to the function, with the named example. Should I then
unpack the resulting tuple into corresponding first,second,third...
dictionaries for further processing?


I am also wondering if this is even the right approach? Can this be done
with only unnamed arguments, or do I at least need to name the first
argument for the first reference dictionary, and then use an *unnamed
for each additional dictionary?



Thanks for any pointers,

Colin

Hi Colin,

The problem is that somedicts is indeed a tuple -- having *args in a function def collects non-positional, non-keyword arguments into a tuple. So, in your function body, somedicts is a tuple of dicts. (It's not that each dict is somehow tuplized.)

See if this helps:

>>> def print_values(*some_dicts):
...     for a_dict in some_dicts:
...             for key in a_dict:
...                     print a_dict[key]
...
>>> d1 = {1:2, 3:4}
>>> d2 = {1:42, 2:84}
>>> print_values(d1, d2)
2
4
42
84

Best,

Brian vdB

_______________________________________________
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor

Reply via email to