3.3. Star Parameters

  • Variadic function

  • * is used for positional parameters

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

  • *args unpacks to tuple

  • ** is used for keyword parameters

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

  • **kwargs unpacks to dict

../../_images/unpack-assignment%2Cargs%2Cparams.png

3.3.1. Syntax

>>> def login(*args):
...     return ...
>>> def login(**kwargs):
...     return ...
>>> def login(*args, **kwargs):
...     return ...

3.3.2. Recap

  • Parameter - variable in function signature (function definition)

  • Parameter can be: required or optional

  • Required parameters - necessary to function call

  • Optional parameters - has default value

  • After first optional parameter, all following parameters must also be optional

Required parameters:

>>> def login(username, password):
...     ...

Optional parameters:

>>> def login(username=None, password=None):
...     ...

Required and optional parameters:

>>> def login(username, password=None):
...     ...

3.3.3. Positional Parameters

  • * is used for positional parameters

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

  • *args unpacks to tuple

>>> def login(username, password, *args):
...     print(f'{username=}, {password=}, {args=}')
>>>
>>>
>>> login('alice', 'secret')
username='alice', password='secret', args=()
>>>
>>> login('alice', 'secret', True)
username='alice', password='secret', args=(True,)
>>>
>>> login('alice', 'secret', True, 3600)
username='alice', password='secret', args=(True, 3600)

3.3.4. Keyword Parameters

  • ** is used for keyword parameters

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

  • **kwargs unpacks to dict

>>> def login(username, password, **kwargs):
...     print(f'{username=}, {password=}, {kwargs=}')
>>>
>>>
>>> login('alice', 'secret')
username='alice', password='secret', kwargs={}
>>>
>>> login('alice', 'secret', remember_me=True)
username='alice', password='secret', kwargs={'remember_me': True}
>>>
>>> login('alice', 'secret', remember_me=True, timeout=3600)
username='alice', password='secret', kwargs={'remember_me': True, 'timeout': 3600}

3.3.5. Positional and Keyword Parameters

  • * is used for positional parameters

  • ** is used for keyword parameters

  • *args unpacks to tuple

  • **kwargs unpacks to dict

>>> def login(username, password, *args, **kwargs):
...     print(f'{username=}, {password=}, {args=}, {kwargs=}')
>>>
>>>
>>> login('alice', 'secret')
username='alice', password='secret', args=(), kwargs={}
>>>
>>> login('alice', 'secret', True, 3600)
username='alice', password='secret', args=(True, 3600), kwargs={}
>>>
>>> login('alice', 'secret', True, timeout=3600)
username='alice', password='secret', args=(True,), kwargs={'timeout': 3600}
>>>
>>> login('alice', 'secret', remember_me=True, timeout=3600)
username='alice', password='secret', args=(), kwargs={'remember_me': True, 'timeout': 3600}

3.3.6. Case Study

class ContextMixin:
    extra_context = None

    def get_context_data(self, **kwargs): ...
class View:
    http_method_names = ["get", "post", "put",  "delete"]

    def __init__(self, **kwargs): ...
    def view_is_async(cls): ...
    def as_view(cls, **initkwargs): ...
    def setup(self, request, *args, **kwargs): ...
    def dispatch(self, request, *args, **kwargs): ...
    def http_method_not_allowed(self, request, *args, **kwargs): ...
    def options(self, request, *args, **kwargs): ...
    def _allowed_methods(self): ...
from django.views.generic.base import TemplateResponse


class TemplateResponseMixin:
    template_name = None
    template_engine = None
    response_class = TemplateResponse
    content_type = None

    def render_to_response(self, context, **response_kwargs): ...
    def get_template_names(self): ...
from django.views.generic.base import TemplateResponseMixin, ContextMixin, View


class TemplateView(TemplateResponseMixin, ContextMixin, View):
    def get(self, request, *args, **kwargs): ...
from django.views import View


class RedirectView(View):
    permanent = False
    url = None
    pattern_name = None
    query_string = False

    def get_redirect_url(self, *args, **kwargs): ...
    def get(self, request, *args, **kwargs): ...
    def head(self, request, *args, **kwargs): ...
    def post(self, request, *args, **kwargs): ...
    def options(self, request, *args, **kwargs): ...
    def delete(self, request, *args, **kwargs): ...
    def put(self, request, *args, **kwargs): ...
    def patch(self, request, *args, **kwargs): ...

3.3.7. Use Case - 1

>>> def add(*values):
...     total = 0
...     for value in values:
...         total += value
...     return total
>>>
>>>
>>> add()
0
>>>
>>> add(1)
1
>>>
>>> add(1, 4)
5
>>>
>>> add(3, 1)
4
>>>
>>> add(1, 2, 3, 4)
10

3.3.8. Use Case - 2

>>> def celsius_to_kelvin(*degrees):
...     return [x+273.15 for x in degrees]
>>>
>>>
>>> celsius_to_kelvin(1)
[274.15]
>>>
>>> celsius_to_kelvin(1, 2, 3, 4, 5)
[274.15, 275.15, 276.15, 277.15, 278.15]

3.3.9. Use Case - 3

>>> def html_list(*fruits):
...     print('<ul>')
...     for fruit in fruits:
...         print(f'<li>{fruit}</li>')
...     print('</ul>')
>>>
>>>
>>> html_list('apple', 'banana', 'orange')
<ul>
<li>apple</li>
<li>banana</li>
<li>orange</li>
</ul>

3.3.10. Use Case - 4

Intuitive definition of print function:

>>> print('hello')
hello
>>>
>>> print('hello', 'world')
hello world
>>>
>>> print('hello', 'new', 'world')
hello new world
>>> def print(*values, sep=' ', end='\n'):
...     return sep.join(values) + end

3.3.11. Assignments

# %% About
# - Name: Star Parameters Args
# - Difficulty: easy
# - Lines: 1
# - Minutes: 2

# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% English
# 1. Define a variadic function `run()`,
#    which can takes arbitrary number of positional arguments
# 2. Function does nothing (pass)
# 3. Run doctests - all must succeed

# %% Polish
# 1. Zdefiniuj wariadyczną funkcję `run()`,
#    która przyjmuje nieskończoną liczbę pozycyjnych argumentów
# 2. Funkcja nic nie robi (pass)
# 3. Uruchom doctesty - wszystkie muszą się powieść

# %% Hints
# - `*args`

# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> run()
>>> run(1)
>>> run(1, 2)
>>> run(1, 2, 3)
>>> run(1, 2, 3, 4)
>>> run(1, 2, 3, 4, 5)
"""

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`

# %% Imports

# %% Types
from typing import Callable
run: Callable[[...], None]

# %% Data

# %% Result
def run():
    pass

# %% About
# - Name: Star Parameters Kwargs
# - Difficulty: easy
# - Lines: 1
# - Minutes: 2

# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% English
# 1. Define a variadic function `run()`,
#    which can takes arbitrary number of keyword arguments
# 2. Function does nothing (pass)
# 3. Run doctests - all must succeed

# %% Polish
# 1. Zdefiniuj wariadyczną funkcję `run()`,
#    która przyjmuje nieskończoną liczbę nazwanych argumentów
# 2. Funkcja nic nie robi (pass)
# 3. Uruchom doctesty - wszystkie muszą się powieść

# %% Hints
# - `*args`

# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> run()
>>> run(a=1)
>>> run(a=1, b=2)
>>> run(a=1, b=2, c=3)
>>> run(a=1, b=2, c=3, d=4)
>>> run(a=1, b=2, c=3, d=4, e=5)
"""

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`

# %% Imports

# %% Types
from typing import Callable
run: Callable[[...], None]

# %% Data

# %% Result
def run():
    pass

# %% About
# - Name: Star Parameters ArgsKwargs
# - Difficulty: easy
# - Lines: 1
# - Minutes: 2

# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% English
# 1. Define a variadic function `run()`,
#    which can takes arbitrary number of positional and keyword arguments
# 2. Function does nothing (pass)
# 3. Run doctests - all must succeed

# %% Polish
# 1. Zdefiniuj wariadyczną funkcję `run()`,
#    która przyjmuje nieskończoną liczbę pozycyjnych i nazwanych argumentów
# 2. Funkcja nic nie robi (pass)
# 3. Uruchom doctesty - wszystkie muszą się powieść

# %% Hints
# - `*args`

# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> run()
>>> run(1)
>>> run(a=1)
>>> run(1, 2)
>>> run(a=1, b=2)
>>> run(1, b=2)
>>> run(1, 2, 3)
>>> run(1, 2, c=3)
>>> run(1, b=2, c=3)
>>> run(a=1, b=2, c=3)
"""

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`

# %% Imports

# %% Types
from typing import Callable
run: Callable[[...], None]

# %% Data

# %% Result
def run():
    pass