### Functions Intro II

An Diving Deeper into Function Arguments

## 5. Diving Deeper into Function Arguments

There are several ways to feed arguments into a Python function, allowing for a lot of flexibility. Let's go through some of the most important ones:

### 5.1 Positional Arguments

Positional arguments are the most basic type of argument. They're called "positional" because the order in which you pass them matters. For instance:

``````
def greet(name, greeting):
print(f'{greeting}, {name}!')

greet('Alice', 'Hello')  # prints: Hello, Alice!
```
```

In this example, 'Alice' is the first argument and 'Hello' is the second argument. Their order matches the order of parameters in the function declaration.

### 5.2 Keyword Arguments

Keyword arguments are identified by the keyword used before them when calling the function. You can use keyword arguments to make your code more readable or to specify default values for parameters:

``````
def greet(name, greeting='Hello'):
print(f'{greeting}, {name}!')

greet(name='Alice', greeting='Hi')  # prints: Hi, Alice!
greet(name='Bob')  # prints: Hello, Bob!
```
```

As you can see, keyword arguments also allow you to call parameters out of order because they're explicitly matched by name, not by position. In the second call to `greet`, we only provided a value for `name`. The `greeting` parameter defaulted to 'Hello'.

### 5.3 Variable-Length Arguments

Sometimes, you might want a function to take any number of arguments. Python allows for this with *args and **kwargs:

``````
def print_args(*args):
for arg in args:
print(arg)

print_args('Alice', 'Bob', 'Charlie')  # prints: Alice\nBob\nCharlie

def print_kwargs(**kwargs):
for key, value in kwargs.items():
print(f'{key}: {value}')

print_kwargs(name='Alice', age=25, occupation='Engineer')  # prints: name: Alice\nage: 25\noccupation: Engineer
```
```

In these examples, `*args` gathers positional arguments into a tuple, and `**kwargs` gathers keyword arguments into a dictionary.

### 5.4 Mixing Argument Types

You can mix positional arguments, keyword arguments, and variable-length arguments in many ways, but they must appear in a specific order: first any positional parameters, then *args, then keyword parameters, then **kwargs:

``````
def example_function(arg1, arg2, *args, kwarg1='default', kwarg2='default', **kwargs):
pass
```
```

This function can take a wide variety of arguments. It requires at least two, `arg1` and `arg2`, but all the rest are optional.

Understanding how to feed arguments into functions can make your Python code much more flexible and powerful. With practice, you'll get a feel for how to use these different types of arguments effectively.