[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