In Python, you define a function to make a code that performs this operation. To do this, you need to call a function with a value, which is called a function argument in Python.
We define a function that takes 2 arguments. It is a function for the addition of 2 numbers.
Example of the function to add 2 numbers:
def add(x1,x2): print("sum:", x1+x2) add(14,16) #Output: #sum: 30
As you can see in this program add() function needs to take 2 arguments x1 and x2. We get a sum of two numbers as a result when we pass two values while calling the function. But if we need to get a sum of 4 numbers. Let’s see what happens when we pass 4 numbers instead of 2 in the add() function.
def add(x1,x2): print("sum:",x1+x2) add(9,11,13,15)
When we run the above program, we get output like these:
#Output: #TypeError: add() takes 2 positional arguments but 4 were given
In conclusion, we can say that you can’t pass more arguments in a function, because it has a limited quantity of arguments. But what if you need to sum up a different number of arguments? It would be good if we can create a function, where the number of arguments passed is only determined at runtime.
Here come *args and **kwargs. Args and kwargs in Python allow you to pass a variable number of arguments to a function. For, this you only need to use them as arguments in a function. At first, you need to understand the difference between *args and **kwargs. *args in Python are non keyword arguments and **kwargs mean keyword arguments in Python.
Keyword and non-keyword arguments
Let’s start from the basics. Arguments to built-in functions (or methods) can be passed by keyword parameter in Python, and the language has the ability to collect both positional and/or keyword arguments in a single call.
Positional or, in our case, non-keyword arguments are moved into the function by the order in which the parameters were recorded during the interpretation of the function. Therefore, it means that the order of arguments and parameters in Python is strongly important as the values passed to these functions are assigned to the analogous parameters based on their position. Actually, they are matched from left to right.
Example of using non-keyword arguments:
def example(name, date): print(name + "`s birthday is on", date) example("David", "12/01/2001") #Output: #David`s birthday is on 12/01/2001
Here are name and date are the arguments that are strongly located in the order 1.name 2.date. So when we use the function we need to type it in the same form.
Keyword arguments (or named arguments) are values that, when preceded by a function, are identified by specific parameter names. The key argument is passed by a parameter and the operator = that assigns it. Keyword arguments can be compared to dictionaries in that they map a value to a keyword. Therefore, the order in which these arguments are passed to the caller does not matter, as they correspond to the argument name.
def example(name, date): print(name + "`s birthday is on", date) example(date = "12/01/2001", name = "David") #Output: #David`s birthday is in 12/01/2001
And as mentioned already, the order that we provide keyword arguments doesn’t really matter: here name and date are not located in the same order as defined in the function. We used the name of an argument and made it equal to the content needed for it.
Take note that we can even make a function where non-keyword arguments are with keyword arguments, but take note again that if you provide a keyword argument before non-keyword, you can get SyntaxError
Let’s see two examples:
def example(name, date, location): print(name, "is making birthday on", date, "in the", location) example("David", location = "school", date="12/01/2001") #Output: #David is making birthday on 12/01/2001 in the school
We used different types of arguments. Here the argument ‘name’ became a positional argument and ‘location’ and ‘date’ – keyword argument. The next example will have a mistake:
def example(name, date, location): print(name, "is making birthday on", date, "in the", location) example(location = "school", "David", date="12/01/2001") #Output: #SyntaxError: positional argument follows keyword argument
And the mistake is that we have put the positional argument after the keyword argument. Again ‘name’ is the non-keyword argument and the other two are keyword arguments.
Python *args
In the example above the number of arguments is established, so we can not decide ourselves how many arguments to pass. Python arg can help us in this situation by passing the variable number of non keyword arguments to function. In the parentheses we need to use an asterisk * before the name of the keyword parameter Python to pass a variable quantity of arguments. Arguments are passed as a tuple, and those passed arguments create a tuple in a function with the same name as the parameter, excluding *.
Python argument passing example:
def multiply(x): print(x*x) multiply(13) #Output: #169
And the example using *arg Python:
def example(*args): print(args) example(13, 14, 16) #Output: #(13, 14, 16)
So actually we can improve our function to sum 4 numbers, 2 or another one you want. Take note that name *args here is just the name and we can use another one that we prefer.
Example of using *args Python named as *numbers:
def add(*numbers): sum = 0 for n in numbers: sum = sum + n print("sum:",sum) add(13,14) add(13,15,17,19) #Output: #sum: 27 #sum: 64
Here we used *numbers as a parameter so we are allowed to pass a variable quantity of argument lists to add() function. As you can see, we have created a loop that adds the passed argument inside the function and prints the result. *numbers takes all parameters that we have provided in the input and then packs them into a single iterable object named args. So we have passed 2 different tuples with variable lengths.
Using the Python args Variable in definitions of the Functions
Undoubtedly, there can be a lot of ways to pass varying lengths of arguments to the function. But using argss is one of the simplest. We can simply pass the whole list or a set of all arguments to our function. Here is an example of a harder way how to do it:
def sumOfElements(numbers_list): example_list = 0 for n in numbers_list: example_list += n return example_list list_of_numbers = [14, 15.5, 145] print("sum of elements:", sumOfElements(list_of_numbers)) #Output: #sum of elements: 174.5
So here we created the list and passed it into the function. This way can be useful when we already know what integers we want to use. But what to do when we want to implement elements into the function and we do not know what they are? Here is where our *args comes into our function.
Args python example we have already seen before:
def sumOfElements(*numbers): example_list = 0 for n in numbers: example_list += n print("sum of elements:",example_list) sumOfElements(14, 15.5, 145) #Output: #sum of elements: 174.5
And here we see that all elements are added after the function. So it is more easier and more convenient for us to use *args in the function.
Also, we can make the opposite usage of asterisk operators, where the asterisk symbol will not be used when we define the function, but when we call it:
def personal_name(first, second, third): print("Name:", first) print("Middle name:", second) print("Surname:", third) args = ("John", "Fitzgerald", "Kennedy") personal_name(*args) #Output: # Name: John # Middle name: Fitzgerald # Surname: Kennedy
def personal_name(first, second, third): print("Name:", first) print("Middle name:", second) print("Surname:", third) args = ("John", "Fitzgerald", "Kennedy") personal_name(*args) #Output: # Name: John # Middle name: Fitzgerald # Surname: Kennedy
Here we created three parameters: first, second, and third. We created a variable args that will be our tuple. Asterisk syntax helped us to pass the variable into the function.
Also, we can combine already-named parameters with the arg in Python. Here is an example:
Python kwargs tutorial
**kwargs are useful for passing a variable length of arguments to a Python function. In the parentheses we use two asterisks ** before the name of the parameter to denote the type of argument. Python keyword arguments are passed as a dictionary, as we know now *args are passed as a tuple, and those passed arguments create the dictionary in the function with the same name as the parameter, excluding **. Similar to *args example, let’s try to make an example of **kwargs:
def example(**kwargs): print(kwargs) example(13, 14, 16) #Output: #TypeError: example() takes 0 positional arguments but 3 were given
And we have got a TypeError. The next example of using kwargs Python will explain why it happened:
def example(**kwargs): print(kwargs) example(first = 13, second = 14, third = 16) #Output: #{'first': 13, 'second': 14, 'third': 16}
Here we can see, that the main difference between *args and **kwargs is the difference of the types. When using *args we create a tuple, **kwargs only receive dictionaries. Don’t forget that name don’t need to be **kwargs again. It can be another one that we prefer, but be careful with asterisks!
def example(**kwargs): for first, second in kwargs.items(): print("{0} is {1}".format(first, second)) example(Name="Kevin") #Output: #Name is Kevin
Here we used the .format() string method to specify values and insert them inside the string’s placeholder. kwarg helps us to work with the Name variable, so we can take the content from it and push it in the curly brackets of the .format(first, second).
Using the Python kwargs Variable in definitions of Functions
So now we have understood what are **kwargs. They work same as *args but instead of non-keyword arguments it accepts keyword ones. Let’s make an example so we can see why **kwargs are useful enough:
def example(**sentence): example_list = "" for n in sentence.values(): example_list += n print(sentence) example(a="Good ", b="morning, ", c="KoderShop", d="!") #Output: #{'a': 'Good ', 'b': 'morning, ', 'c': 'KoderShop', 'd': '!'}
Making some formatting we can make it more readable:
def example(**sentence): example_list = "" for n in sentence.values(): example_list += n return example_list print(example(a="Good ", b="morning, ", c="KoderShop", d="!")) #Output: #Good morning, KoderShop!
Here we used print features to make the code look more accurate and now we can actually see how good **kwargs is. Note that in the example above, the iterated object is a standart dict. If you are looping through a kwargs dictionary and want to return its values, as in the example above, you should use .values().
In another situation, if you want to take only keys in the dictionary, you need to remove .values(), like in the example below:
def example(**sentence): example_list = "" for n in sentence: example_list += n return example_list print(example(a="Good ", b="morning, ", c="KoderShop", d="!")) #Output: #abcd
When can we use them?
It really depends on the requirements. The most common use case of args kwargs Python is to create function decorators. In addition, it can also be used to repair monkeys. Let’s say you have a class with a get_info function that calls an API and returns response data. If we want to test this, we can replace the API call with test data. Sounds difficult, but undoubtedly I think Python args kwargs can have a lot of ways to make them useful.
Function order of the arguments
When we create a function that takes a changeable number of both positional and named arguments, the order counts. Take a note, or learn by heart the set order when ordering args in a function and undoubtedly function call. The *args like non-default arguments have to precede the **kwargs that are like default arguments. Let’s see the correct order of parameters:
First – Standard arguments;
Second – *args;
And the last – **kwargs.
The next question is: what happens if we define a function with non-correct order of parameters? Here is an example:
def example(**sentence, *args, x): print("Is it right?") #Output: #def example(**sentence, *args, x): # ^ #SyntaxError: invalid syntax
Here we can see that **kwargs precedes *args in a function definition. If you try to run this example, you immediately get an error message from the interpreter and it does not matter what you have written next in the code.
The correct ones will look like that:
def example(*numbers, **keys): words_list = "" sum_of = 0 for n in numbers: sum_of += n for m in keys: words_list += m + ' ' print('Sum of numbers:', sum_of, '\nWords from keys:', words_list) example(1, 2, 12.5, Watch='first', how='second', I='third', can='fourth') #Output: #Sum of numbers: 15.5 #Words from keys: Watch how I can
And here we used 2 arguments *args and **kwargs to complete our sum_of and words_list.
Unpacking operators in Python
We use *args and **kwargs to define Python functions that accept different numbers of input arguments. Let’s understand a bit more about these operators.
These single and double operators are in Python from the Python 2.
Single and double star unpacking operators were introduced in Python 2. As people say, they have become more powerful only in Python 3 thanks to PEP 448, which was created in June 2013.
This PEP offers extended use of the * iterative unpacking operator and the ** dictionary unpacking operators to allow us to use it in more positions under additional circumstances, such as function calls, in generator understandings and expressions, and in mappings. So what are these “unpacking operators”?
In short, unpacking operators are operators that unpack values from iterated objects in Python. The single-star * operator can be used for any iterator that Python provides, while the double-star ** operator can only be used for dictionaries.
Unpacking lists
Let’s see some examples of lists:
example_list = ['Hello,', 'KoderShop', '!'] print(example_list) #Output: #['Hello,', 'KoderShop', '!']
Here we see how the standard output of the list works. We have square brackets, commas and our values. We do not want that. Now we gonna use unpacking operator *. What will the output be?
example_list = ['Hello,', 'KoderShop!'] print(*example_list) #Output: #Hello, KoderShop!
So here the asterisk operator talks with print and makes it unpack the list first. We do not have these annoying brackets and commas and can see only the content of the list. And also we have changed arguments so the content in the output will look more clear.
It is one explanation of what asterisks can do. They make print() in-built functions take these two separate arguments as the input.
Calling functions
This asterisk method we can use to call our functions. The only rule is that we should make the iterable we unpack to have the same number of arguments if we want our function to have a specific number of arguments.
def example(first, second, third): print(first * second * third) example_list = [1, 2, 3] example(*example_list) #Output: #6
So we have here the *example_list which means that we have unpacked our list and used only content from it to make the multiplication we need. Try yourself, what will happen without the asterisk…
def example(first, second, third): print(first * second * third) example_list = [1, 2, 3] example(example_list) #Output: #TypeError: example() missing 2 required positional arguments: 'second' and 'third'
Before the example of an error, we had 3 elements in our example_list that meet up the required arguments in example().
Example, where the function requires 5 arguments, but we make only 3:
def example(first, second, third): print(first * second * third) example_list = [1, 2, 3, 4, 5] example(*example_list) #Output: #TypeError: example() takes 3 positional arguments but 5 were given
Here we see how the Python interpreter is unable to run it because example() expects 3 items, but the unpacking operator gets 5 items from our list. The next part of the code will not run.
Several unpacking operators
To unpack the list we use the * unpacking operator so we can pass arguments to a function. It means that we pass every single argument by itself. And again that means using multiple asterisk operators is possible and we get content from several lists. That is all we pass to a single function.
Here is one of the examples:
def sentence(*args): temp = '' for n in args: temp += n print(temp) words1 = ['— Hello, ' 'how ', 'are ', 'you?\n'] words2 = ['― I ', 'am ', 'fine, ', 'thanks. ', 'And ', 'you?\n'] words3 = ['― Me ', 'too.'] sentence(*words1, *words2, *words3) #Output: # — Hello, how are you? # ― I am fine, thanks. And you? # ― Me too.
Running this example, we see that our lists of words were successfully unpacked. Every word was passed to the function sentence() so we can see the speech. In the end of every item, we have added the space so it could look like the normal sentence but not the array of symbols. Also we used the ‘\n’ newline character at the end of the last item in the list.
Split and merge using unpacking operators
Here is another way to use the unpacking operator. For instance, we have a list and our wish is to have it split into three parts, where the last value of the list will be at the end of the output, first value will be at the start, and another value will be between.
example_list = [1, 26, 3.3, 4, 5.3, 6] first, *second, third = example_list print(first) print(second) print(third) #Output: #1 #[26, 3.3, 4, 5.3] #6
Here we see 6 items in the example_list. We create 3 variables. First(example_list[0]) must be at the start, *second at the middle, and third(example_list[5]) at the end. The new list *second is a created list of all other elements. In the output section we see how to print() shows us our three variables have the values we expected.
Also using unpacking operators * we can split items of iterable objects. For example, we decided to merge two lists, so it could be useful:
first = 1 second = [26, 3.3, 4, 5.3] third = 6 example_list = [first,*second,third] print(example_list) #Output: #[1, 26, 3.3, 4, 5.3, 6]
As it worked before it worked also here. *second took all the elements from the second list inside and added them into the example_list. Integers from the first and third were added using standard in-built syntax.
Asterisk operators can also even merge two different dictionaries. We need to use now double-asterisk operator **:
first = {'Ab':3, 'Cd':2} second = {'Ef':1} example_list = {**first,**second} print(example_list) #Output: #{'Ab': 3, 'Cd': 2, 'Ef': 1}
So now we created three dictionaries, where the third one example_list is the merged list from two others. Firstly, we can see that now we use curly brackets, so we know that they are dictionaries, and also double-asterisk operators, to show that we are working with dictionaries.
Another feature of unpacking operators is unpacking strings. Remember now that * operator is used on any iterable object. Let’s see some examples of string:
example = [*"KoderShop is the best!"] print(example) #Output: #['K', 'o', 'd', 'e', 'r', 'S', 'h', 'o', 'p', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 'b', 'e', 's', 't', '!']
Here we can see how * operator made the split of the symbols from the string. Strings are iterable in Python, so it’s why we got such a result after unpacking.
Take a minute, and think how the next example differs from the example above.
Here we can see how * operator made the split of the symbols from the string. Strings are iterable in Python, so it’s why we got such a result after unpacking.
Take a minute, and think how the next example differs from the example above.
*example, = ["KoderShop is the best!"] print(example) #Output: #['KoderShop is the best!']
Yes, you are right. In one line we got the * operator then a variable and then a comma. We created a new list called example, which takes the “KoderShop is the best!”. The comma makes a thing. When we use the asterisk operator for assigning a new variable, Python requires that the result be a list or a tuple. With the following comma, we have already defined that we have a tuple with the name: example, and which letters are the same as in the example before that: [‘K’, ‘o’, ‘d’, ‘e’, ‘r’, ‘S’, ‘h’, ‘o’, ‘p’, ‘ ‘, ‘i’, ‘s’, ‘ ‘, ‘t’, ‘h’, ‘e’, ‘ ‘, ‘b’, ‘e’, ‘s’, ‘t’, ‘!’].