*ARGS & **KWARGS in Python are Awesome
Tags: webdev, beginners, python, programming
Published: 2023-06-08 20:47:21

Python **args** and **kwargs** are used to pass a variable number of arguments to a function. In this article, I will like to take you through the awesomeness of args and kwargs in python and how they can be used, **args** stands for **arguments** while **kwargs** stands for **keyword-arguments**

## Explaining arbitrary arguments
Arbitrary means a varying number of arguments, we don't always know how many arguments the user is going to pass in when they invoke a function, to accept a varying amount of argument developers turn to use **args** and **kwargs**.
Let's see the example below. Creating a function that will add two numbers together.
```
# *args = allows you to pass multiple non-key arguments
# **args = allows you to pass multiple keyword-arguments
#         *unpacking operator
#         1. position 2. default 3. keyword 4. ARBITRARY

def add(a, b):
    return a + b

print(add(1,2))
```
and we have our output which is:

```
3
```
now what is we will like to pass in 3 parameters?

```
def add(a, b):
    return a + b

print(add(1,2,4))
```
well you can see it returns and error.

```
 print(add(1,2,4))
TypeError: add() takes 2 positional arguments but 3 were given
```
So, what we can do is to modify our function in such a way that it takes varying number of arguments by using the `*args`. What happens when we do this is that we pack all our arguments into a **tuple**. Let me show you what am saying.

```
def add(*args):
    print(type(args))

print(add(1,2,4))
```
and we have 

```
<class 'tuple'>
```
as our results. So, we can use the build in methods of this tuple, or we can iterate over it. Let's iterate our tuple in the example below.

```
def add(*args):
    total = 0
    for arg in args:
        total += arg
    return total
        
print(add(1,2,4))
```
What we have done in the example below is to create variable named `total` to keep track of the total and also, we have `total +=` the current `arg` that we are iterating over, and we have returned the total, and now we have our results.

```
7
```
and now we can add as many arguments as we want. See the example below.

```
def add(*args):
    total = 0
    for arg in args:
        total += arg
    return total

print(add(1,2,4,2,4,5))
```
and we now have our results as

```
18
```
You also change the name of the `*args` to anything let's say `*nums` and you will still have the same results because it is not as important as the `unpacking` operator.

```
def add(*nums):
    total = 0
    for num in nums:
        total += num
    return total

print(add(1,2,4,2,4,5))
```
output

```
18
```
and you can see we still have the same results.
Now let's try another example, a function that will display somebody's name.

```
def display_name(*args):
    for arg in args:
        print(arg, end="")
display_name("Noel", "Bansikah", "Tandap")
```
output:

```
NoelBansikahTandap
```
and you can pass in as many arguments that you want, maybe a title or your best food or game. Following a unique parameter name, you can pack whatever you want into a tuple as I mentioned above.

## **kwargs
Now let's talk about kwargs. **kwargs** stands for **keyword-****arguments** it allows you to pass multiple keyword arguments. See the example below, creating a function that prints an address. Whenever you pass arguments using kwargs, you pack them into a dictionary. To prove this, see below.

```
def print_address(**kwargs):
    print(type(kwargs))
print_address(street="Mile 16",
              city="Buea",
              region="southwest region",
              zip="00237")
```
output

```
<class 'dict'>
```
so, you can treat **kwargs** as if it's a dictionary. Let's iterate over the values to see our results.

```

def print_address(**kwargs):
    for value in kwargs.values():
        print(value)
print_address(street="Mile 16",
              city="Buea",
              region="southwest region",
              zip="00237")
```
output

```
Mile 16
Buea
southwest region
00237
```
and now we have our values printed out, you can use the `keys` method to see the keys in the dictionary.

```

def print_address(**kwargs):
    for key in kwargs.keys():
        print(key)
print_address(street="Mile 16",
              city="Buea",
              region="southwest region",
              zip="00237")
```
Output

```
street
city
region
zip
```
and we have our keys printed out.
To see everything both keys and values, you can use the `items` method.

```
def print_address(**kwargs):
    for key,value in kwargs.items():
        print(f"{key}: {value}")
print_address(street="Mile 16",
              city="Buea",
              region="southwest region",
              zip="00237")
```
Output

```
street: Mile 16
city: Buea
region: southwest region
zip: 00237
```
and now you have all your outputs printed out.

Before we continue i will just like to recommend that if you don't have a detailed understanding about dictionaries, you can check this article [Dictionaries in Python Explained](https://dev.to/bansikah/dictionaries-in-python-explained-1hcc).
In the example above, we can add in a vary number of keyword-arguments. Let's add apartment number.

```
def print_address(**kwargs):
    for key,value in kwargs.items():
        print(f"{key}: {value}")
print_address(street="Mile 16",
              apt="100",//added apartment no.
              city="Buea",
              region="southwest region",
              zip="00237")
```
Output

```
street: Mile 16
apt: 100
city: Buea
region: southwest region
zip: 00237
```
and now you can see apartment no. is packed with our previous arguments.
In our next example, we are going to use both `*args` and `**kwargs` for better understanding. We will print a shipping label.

```

def shipping_label(*args, **kwargs):
    for arg in args:
        print(arg, end="")

    for value in kwargs.values():
        print(value, end="")
shipping_label("Noel", "Bansikah", "Tandap",
              street="Mile 16",
              apt="100",
              city="Buea",
              region="southwest region",
              zip="00237"
)
```
Output

```
Noel  Bansikah  Tandap  Mile 16  100  Buea  southwest region  00237 
```
To print our output neat and separately, we can do this.

```
def shipping_label(*args, **kwargs):
    for arg in args:
        print(arg, end="")

    print(f"{kwargs.get('street')} {kwargs.get('apt')}")
    print(f"{kwargs.get('city')} {kwargs.get('state')}, {kwargs.get('zip')}")
shipping_label(" Noel ", " Bansikah ", " Tandap ",
              street=" Mile 16 ",
              apt=" 100 ",
              city=" Buea ",
              region=" southwest region ",
              zip=" 00237 "
)
```
Output

```
Noel  Bansikah  Tandap  Mile 16   100 
 Buea  None,  00237 
```
You can check if our print statement is setup to print an apartment and street, but the user doesn't have an apartment? as we can see above it will display `none` but we don't want that, so we can solve that by using `if` and `else` statements.

```
def shipping_label(*args, **kwargs):
    for arg in args:
        print(arg, end="")
    if "apt" in kwargs:
        print(f"{kwargs.get('street')} {kwargs.get('apt')}")
    else:
        print(f"{kwargs.get('street')}")
        print(f"{kwargs.get('city')} {kwargs.get('state')}, {kwargs.get('zip')}")
shipping_label(" Noel ", " Bansikah ", " Tandap ",
              street=" Mile 16 ",
              # apt=" 100 ",
              city=" Buea ",
              region=" southwest region ",
              zip=" 00237 "
)
```
output

```
Noel  Bansikah  Tandap  Mile 16 
 Buea   southwest region ,  00237 
```
and you can see that we have solved that problem of it displaying `none`.
Now what if a user has a POX, let's see how we can add that

```
def shipping_label(*args, **kwargs):
    for arg in args:
        print(arg, end="")
    if "apt" in kwargs:
        print(f"{kwargs.get('street')} {kwargs.get('apt')}")
    elif "pobox" in kwargs:
        print(f"{kwargs.get('street')}")
        print(f"{kwargs.get('pobox')}")
    else:
        print(f"{kwargs.get('street')}")
        print(f"{kwargs.get('city')} {kwargs.get('region')}, {kwargs.get('zip')}")
shipping_label(" Noel ", " Bansikah ", " Tandap ",
              street=" Mile 16 ",
              pobox=" #1001 ",
              city=" Buea ",
              region=" southwest region ",
              zip=" 00237 "
)
```
Output

```
Noel  Bansikah  Tandap  Mile 16 
 #1001 
```
and now you can see the user's `pobox` is been added.
So that's all about arbitrary arguments and arbitrary keyword-arguments.

## Summary

***args**: allows you to pass multiple non-key arguments, these arguments are packed in a tuple.
kwargs: allos you to pass multiple keyword-arguments and these arguments are packed in a dictionary.