# 3. Passing many arguments

## 3.1. Arbitrary number of positional arguments

• `*` in this context, is not multiplication in mathematical sense

• `*` is used for positional arguments

• `args` is a convention, but you can use any name

• `*args` unpacks from `tuple`, `list` or `set`

```def echo(a, b, c=0):
print(a)    # 1
print(b)    # 2
print(c)    # 0

echo(1, 2)
```
```def echo(a, b, c=0):
print(a)    # 1
print(b)    # 2
print(c)    # 0

args = (1, 2)
echo(*args)
```

## 3.2. Arbitrary number of keyword arguments

• `**` in this context, is not power in mathematical sense

• `**` is used for keyword arguments

• `kwargs` is a convention, but you can use any name

• `**kwargs` unpacks from `dict`

```def echo(a, b, c=0):
print(a)    # 1
print(b)    # 2
print(c)    # 0

echo(a=1, b=2)
```
```def echo(a, b, c=0):
print(a)    # 1
print(b)    # 2
print(c)    # 0

kwargs = {'a': 1, 'b': 2}
echo(**kwargs)
```

## 3.3. Arbitrary number of positional and keyword arguments

```def echo(a, b, c=0):
print(a)    # 1
print(b)    # 2
print(c)    # 0

echo(1, b=2)
```
```def echo(a, b, c=0):
print(a)    # 1
print(b)    # 2
print(c)    # 0

args = (1,)
kwargs = {'b': 2}

echo(*args, **kwargs)
```

## 3.4. Examples

### 3.4.1. Creating complex numbers

```complex(real=3, imag=5)
# (3+5j)
```
```kwargs = {'real': 3, 'imag': 5}
complex(**kwargs)
# (3+5j)
```

### 3.4.2. Vectors

```def echo(x, y, z):
print(x)    # 1
print(y)    # 0
print(z)    # 1

vector = (1, 0, 1)

echo(*vector)
```

### 3.4.4. Common configuration

```def draw_line(x, y, color, style, width, markers):
...

draw_line(1, 2, color='red', style='dashed', width='2px', markers='disc')
draw_line(3, 4, color='red', style='dashed', width='2px', markers='disc')
draw_line(5, 6, color='red', style='dashed', width='2px', markers='disc')
```
Listing 95. Podawanie parametrów do funkcji
```def draw_chart(a, b, color, style, width, markers):
...

config = {
'color': 'czerwony',
'style': 'dashed',
'width': '2px',
'markers': 'disc',
}

draw_line(1, 2, **config)
draw_line(3, 4, **config)
draw_line(5, 6, **config)
```

### 3.4.5. Calling function with all variables from higher order function

```def lower(*args, **kwargs):
print(f'args: {args}')
print(f'kwargs: {kwargs}')

def higher(a, b, c=0):
d = 4
e = 5
lower(**locals())
# lower(a=a, b=b, c=c, d=d, e=e)

higher(1, 2)
# args: ()
# kwargs: {'a': 1, 'b': 2, 'c': 0, 'd': 4, 'e': 5}
```

### 3.4.6. Proxy functions

Listing 96. One of the most common use of `*args`, `**kwargs` is for proxy methods.
```# ``read_csv`` is a function from ``pandas`` library
usecols=None, squeeze=False, prefix=None,
mangle_dupe_cols=True, dtype=None, engine=None,
converters=None, true_values=None, false_values=None,
skipinitialspace=False, skiprows=None, nrows=None,
na_values=None, keep_default_na=True, na_filter=True,
verbose=False, skip_blank_lines=True, parse_dates=False,
infer_datetime_format=False, keep_date_col=False,
date_parser=None, dayfirst=False, iterator=False,
chunksize=None, compression='infer', thousands=None,
decimal=b'.', lineterminator=None, quotechar='"',
quoting=0, escapechar=None, comment=None, encoding=None,
delim_whitespace=False, low_memory=True, memory_map=False,
float_precision=None):
...

def my_csv(file, encoding='utf-8', *args, **kwargs):
encoding=encoding,
*args,
**kwargs)

my_csv('iris1.csv')
my_csv('iris2.csv', encoding='iso-8859-2')
my_csv('iris3.csv', encoding='cp1250', verbose=True)
my_csv('iris4.csv', verbose=True)
```

### 3.4.7. Decorators

```def login_required(original_function):

def wrapper(*args, **kwargs):
user = kwargs['request'].user

if user.is_authenticated():
return original_function(*args, **kwargs)
else:
print('Permission denied')

return wrapper

def edit_profile(request):
...
```

## 3.5. Assignments

### 3.5.1. Iris

1. Otwórz link w przeglądarce i skopiuj zawartość do pliku na dysku o nazwie `iris.csv`

2. Z pliku `iris.csv` odseparuj nagłówek i dane

3. Z nagłówka odrzuć rekord `species`

4. Stwórz funkcję `print_iris(species, **pomiary)`, która wyświetli zawartość wszystkich argumentów za pomocą `locals()`

5. Dla każdego rekordu w danych:

1. Usuń białe spacje

2. Podziel po przecinku `,`

3. Wyniki podziału zapisz do dwóch zmiennych:

• `pomiary: Dict[str, float]` - pomiary

• `gatunek: str` - nazwa gatunku

4. Odpalaj funkcję `print_iris()`, podając wartości `pomiary` i `gatunek`

5. `gatunek` ma być podany pozycyjnie

6. `pomiary` mają być podane nazwanie