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
def read_csv(filepath_or_buffer, sep=', ', delimiter=None,
             header='infer', names=None, index_col=None,
             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,
             dialect=None, tupleize_cols=None, error_bad_lines=True,
             warn_bad_lines=True, skipfooter=0, doublequote=True,
             delim_whitespace=False, low_memory=True, memory_map=False,
             float_precision=None):
    ...

def my_csv(file, encoding='utf-8', *args, **kwargs):
    return read_csv(file,
                    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


@login_required
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