|Programmer's Python - Parameters|
|Written by Mike James|
|Monday, 11 January 2021|
Page 2 of 2
Suppose you want to define a function which can accept any number of parameters. The solution to this is to specify a parameter of the form *name. In this case all of the arguments, as many as supplied, are packed into a tuple ready for you to process.
def sum(*nums): total=0 for n in nums: total=total+n return total
Notice that the parameter when used within the function doesn’t have the * prefix. You can now call sum with as many numbers to add up as you require:
You can also specify a variable set of parameters after a number of positional parameters.
def sum(a,b,*nums): total=a+b for n in nums: total=total+n return total print(sum(1,2,3,4,5))
In this case 1 and 2 are stored in a and b, and the remainder of the arguments are stored in nums as a tuple.
You obviously can’t have any positional parameters beyond a catch all *name but you can have keyword only parameters. For example:
def sum(*nums,a,b): total=a+b for n in nums: total=total+n return total
If you just call this version of sum with positional arguments you will see an error message. You have to call this with named parameters:
It doesn’t matter where you specify the named parameters but you have to do it – hence the term “keyword only” parameter.
You can also set defaults for keyword only parameters.
def sum(*nums,a=1,b): total=a+b for n in nums: total=total+n return total
Now a is still a keyword only parameter but if you don’t specify a value for it when you call the function, the default will be used. Notice that if you want keyword only parameters to be optional you have to supply a default:
and you cannot omit b because it has no default.
Keyword only parameters are stored in the __kwdefaults__ attribute of the function as a dictionary object.
What about a variable number of arbitrary keyword parameters?
In the same way that *name stores any number of positional parameters in a tuple **name will store any number of keyword parameters in a dictionary.
def sum(**namedNums): total=0 for name,value in namedNums.items(): total=total+value print(name,value) return total
creates a function that can only be called using keyword parameters and you can make up the keywords when you call the function.
prints one 1, two 2, three 3 and the sum of the values, 6.
You can also define a function that has any number of positional parameters and any number of keyword parameters by using *name and **name together. Notice that in this case *name has to come first and you can also have some positional parameters as long as they come before *name.
def sum(a,b,*nums,**namedNums): total=a+b for value in nums: total=total+value for name,value in namedNums.items(): total=total+value print(name,value) return total
Now you have to call sum with two positional parameters, but after that you can have as many positional or keyword parameters you want to use.
in this case 1 is stored in a, 2 in b, (3,4) in nums, and the keyword parameters are stored in namedNums.
Unpacking Into Parameters
You can think of *name and **name as being packing operations. They pack the positional and keyword parameters into tuples and dictionaries respectively.
It sometimes happens that what you have is already packed into a tuple or a dictionary and you want to pass it to a function as a parameter list. The easiest solution is to use the unpacking operators * and ** which unpack a tuple or a dictionary respectively.
def sum(a,b): total=a+b return total tuple=(1,2) print(sum(*tuple))
In this case the tuple (1,2) is unpacked into the parameters a and b.
If there are too many parameters after unpacking you will generate an error:
TypeError: sum() takes 2 positional arguments but 4 were given
You can of course avoid this by using the * operator in the function definition:
def sum(a,b,*nums): total=a+b return total
Any unused parameters that result from the unpacking are now packed into a tuple referenced by nums.
The same idea works with dictionaries and keyword parameters:
In this case dict is unpacked into a and b with values 1 and 2 respectively.
As with tuples the parameters have to exist but you can repack the dictionary into a parameter using **name.
Not in this extract:
|Last Updated ( Wednesday, 13 January 2021 )|