def reducefn(*dicts): #collects multiple arguments and stores in dicts
for dic in dicts: #go over each dictionary passed in
for k,v in dic.items(): #go over key,value pairs in the dic
print(k,v)
reducefn({'practical': 1, 'volume': 1, 'physics': 1} ,{'practical': 1, 'volume': 1, 'chemistry': 1})
Produces
>>>
physics 1
practical 1
volume 1
chemistry 1
practical 1
volume 1
Now, regarding your implementation:
def reducefn(k, v):
The function signature above takes two arguments. The arguments passed to the function are accessed via k and v respectively. So an invocation of reducefn({"key1":"value"},{"key2":"value"}) results in k being assigned {"key1":"value"} and v being assigned {"key2":"vlaue"}.
When you try to invoke it like so: reducefn(dic1,dic2,dic3,...) you are passing in more than the allowed number of parameters as defined by the declaration/signature of reducefn.
for k,val in (k,v):
Now, assuming you passed in two dictionaries to reducefn, both k and v would be dictionaries. The for loop above would be equivalent to:
>>> a = {"Name":"A"}
>>> b = {"Name":"B"}
>>> for (d1,d2) in (a,b):
print(d1,d2)
Which gives the following error:
ValueError: need more than 1 value to unpack
This occurs because you're essentially doing this when the for loop is invoked:
d1,d2=a
You can see we get this error when we try that in a REPL
>>> d1,d2=a
Traceback (most recent call last):
File "<pyshell#24>", line 1, in <module>
d1,d2=a
ValueError: need more than 1 value to unpack
We could do this:
>>> for (d1,d2) in [(a,b)]:
print(d1,d2)
{'Name': 'A'} {'Name': 'B'}
Which assigns the tuple (a,b) to d1,d2. This is called unpacking and would look like this:
d1,d2 = (a,b)
However, in our for loop for k,val in (k,v): it wouldn't make sense as we would end up with k,and val representing the same thing as k,v did originally. Instead we need to go over the key,value pairs in the dictionaries. But seeing as we need to cope with n dictionaries, we need to rethink the function definition.
Hence:
def reducefn(*dicts):
When you invoke the function like this:
reducefn({'physics': 1},{'volume': 1, 'chemistry': 1},{'chemistry': 1})
*dicts collects the arguments, in such a way that dicts ends up as:
({'physics': 1}, {'volume': 1, 'chemistry': 1}, {'chemistry': 1})
As you can see, the three dictionaries passed into the function were collected into a tuple. Now we iterate over the tuple:
for dic in dicts:
So now, on each iteration, dic is one of the dictionaries we passed in, so now we go ahead and print out the key,value pairs inside it:
for k,v in dic.items():
print(k,v)