[Tutor] Help with unnamed arguments in a merge function
Brian van den Broek
bvande at po-box.mcgill.ca
Wed Mar 16 08:45:56 CET 2005
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
More information about the Tutor
mailing list