2.4. Unpacking Parameter Syntax

2.4.1. Recap

def echo(a, b, c=3):
     print(a, b, c)


echo(1, 2)              # 1 2 3
echo(1, b=2)            # 1 2 3
echo(1, c=3)            # TypeError: echo() missing 1 required positional argument: 'b'
echo(1, 2, 3)           # 1 2 3
echo(1, 2, c=3)         # 1 2 3
echo(1, b=2, c=3)       # 1 2 3
echo(a=1, b=2, c=3)     # 1 2 3

2.4.2. Keyword-only Parameters

  • All parameters after * must be keyword-only

def echo(a, *, b, c=3):
    print(a, b, c)


echo(1, 2)              # TypeError: echo() takes 1 positional argument but 2 were given
echo(1, b=2)            # 1 2 3
echo(1, c=3)            # TypeError: echo() missing 1 required keyword-only argument: 'b'
echo(1, 2, 3)           # TypeError: echo() takes 1 positional argument but 3 were given
echo(1, 2, c=3)         # TypeError: echo() takes 1 positional argument but 2 positional arguments (and 1 keyword-only argument) were given
echo(1, b=2, c=3)       # 1 2 3
echo(a=1, b=2, c=3)     # 1 2 3

2.4.3. Positional-only Parameters

  • Since Python 3.8: PEP 570 -- Python Positional-Only Parameters

  • All parameters before / must be positional-only

def echo(a, /, b, c=3):
    print(a, b, c)


echo(1, 2)              # 1 2 3
echo(1, b=2)            # 1 2 3
echo(1, c=3)            # TypeError: echo() missing 1 required positional argument: 'b'
echo(1, 2, 3)           # 1 2 3
echo(1, 2, c=3)         # 1 2 3
echo(1, b=2, c=3)       # 1 2 3
echo(a=1, b=2, c=3)     # TypeError: echo() got some positional-only arguments passed as keyword arguments: 'a'

2.4.4. Positional and Keyword Parameters

def echo(a, /, b, *, c=3):
    print(a, b, c)


echo(1, 2)              # 1 2 3
echo(1, b=2)            # 1 2 3
echo(1, c=3)            # TypeError: echo() missing 1 required positional argument: 'b'
echo(1, 2, 3)           # TypeError: echo() takes 2 positional arguments but 3 were given
echo(1, 2, c=3)         # 1 2 3
echo(1, b=2, c=3)       # 1 2 3
echo(a=1, b=2, c=3)     # TypeError: echo() got some positional-only arguments passed as keyword arguments: 'a'

2.4.5. Use Cases

https://docs.python.org/3/library/functions.html#sorted:

sorted(iterable, *, key=None, reverse=False)

https://docs.python.org/3/library/functions.html#sum:

sum(iterable, /, start=0)
def add(a, b, /):
    return a + b
def divmod(a, b, /):
    return (a // b, a % b)
def quantiles(dist, /, *, n=4, method='exclusive')
    ...

2.4.6. Assignments

Code 2.9. Solution
"""
* Assignment: Function Parameter Syntax Kwargs
* Complexity: easy
* Lines of code: 2 lines
* Time: 3 min

English:
    1. Create function `set_position`
    2. Function takes two arguments `x`, `y` and always returns `None`
    3. Arguments must be passed only as keywords
    4. Test function by running with keyword arguments
    5. Test function by running with positional arguments
    6. Run doctests - all must succeed

Polish:
    1. Stwórz funkcję `set_position`
    2. Funkcja przyjmuje dwa argumenty `x`, `y` i zawsze zwraca `None`
    3. Argumenty można podawać tylko nazwanie (keyword)
    4. Przetestuj funkcję uruchamiając z nazwanymi parametrami
    5. Przetestuj funkcję uruchamiając z pozycyjnymi parametrami
    6. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0
    >>> from inspect import isfunction

    >>> assert callable(set_position)
    >>> assert isfunction(set_position)

    >>> set_position(x=1, y=2)

    >>> set_position()
    Traceback (most recent call last):
    TypeError: set_position() missing 2 required keyword-only arguments: 'x' and 'y'

    >>> set_position(1)
    Traceback (most recent call last):
    TypeError: set_position() takes 0 positional arguments but 1 was given

    >>> set_position(1, 2)
    Traceback (most recent call last):
    TypeError: set_position() takes 0 positional arguments but 2 were given

    >>> set_position(1, y=1)
    Traceback (most recent call last):
    TypeError: set_position() takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given

    >>> set_position(x=1, 2)
    Traceback (most recent call last):
    SyntaxError: positional argument follows keyword argument
"""


Code 2.10. Solution
"""
* Assignment: Function Parameter Syntax Args
* Complexity: easy
* Lines of code: 2 lines
* Time: 3 min
* Warning: This assignment will work only in Python 3.8+

English:
    1. Create function `take_damage`
    2. Function takes one argument `dmg` and always returns `None`
    3. Argument must be passed only as positional
    4. Test function by running with positional arguments
    5. Test function by running with keyword arguments
    6. Run doctests - all must succeed

Polish:
    1. Stwórz funkcję `take_damage`
    2. Funkcja przyjmuje jeden argument `dmg` i zawsze zwraca `None`
    3. Argument można podawać tylko pozycyjnie
    4. Przetestuj funkcję uruchamiając z pozycyjnymi parametrami
    5. Przetestuj funkcję uruchamiając z nazwanymi parametrami
    6. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0
    >>> from inspect import isfunction

    >>> assert callable(take_damage)
    >>> assert isfunction(take_damage)

    >>> take_damage(1)
    >>> take_damage(1, 2)
    Traceback (most recent call last):
    TypeError: take_damage() takes 1 positional argument but 2 were given
    >>> take_damage()
    Traceback (most recent call last):
    TypeError: take_damage() missing 1 required positional argument: 'dmg'
    >>> take_damage(dmg=1)
    Traceback (most recent call last):
    TypeError: take_damage() got some positional-only arguments passed as keyword arguments: 'dmg'
"""