Function Syntax and the Python Grammar

June 1, 2022

Overview

Python's grammar specifies how a function may be defined and called. Parameters are used to declare the input variables when a function is defined, and arguments are used to pass values to these parameters when a function is called.

Defining a Function

The grammar of a function definition allows for the specification of required and optional parameters, positional-only and keyword-only parameters, and variable-length parameters. For example, below is a valid function definition:

def f(a, b, /, c, d=1, *e, f=2, g, **h): ...

Required Parameters

Required parameters are parameters defined in a function that must be provided when the function is called (there is no default value).

Required parameters must come before optional parameters for all non keyword-only parameters (ie: everything before the first of either * or **).

Usage:

  • to enforce the order of arguments when the function is called

Examples:

def f(a, b, c):
    ...

Optional Parameters

Optional parameters are parameters defined in a function with an associated default value mapped to them. Optional parameters allow arguments to be omitted when the function is called, with the default value being used if the argument is omitted.

Optional parameters are evaluated once when the module is loaded, not with each call to the function. If the default value is a mutable object, modifications to the value will affect the corresponding object in the calling environment.

Usage:

  • to define sensible defaults and ensure that a function will run without every argument being provided

Examples:

def f(a=1, b=2, c=3):
    ...

Positional-Only Parameters

Positional-only parameters (referenced in PEP 570) are parameters that indicate that the arguments passed into a function call must be done by position only (ie: not by keyword). The / operator is used in the function definition, indicating that all parameters to the left are positional-only parameters.

The / operator may be defined once, and, if exists, at least one positional-only parameter must be defined.

Usage:

  • to prevent function calls being coupled with parameter names that have no semantic meaning or which may change over time
  • to allow a function to accept both positional arguments and keyword arguments with the same name

Examples:

def f(a, b, /, c):
    ...
def f(name, /, **kwargs):
    return 'name' in kwargs

Variable-Length Positional-Only Parameters (*args)

In a function definition, a parameter preceded by a single asterisk (*) indicates argument tuple packing (the parameter name is commonly called *args). The function accepts a variable number of positional arguments which will be unpacked as a tuple.

The * operator cannot have a default value.

Usage:

  • to allow a variable number of positional arguments to be passed into the function

Examples:

def f(*args):
    ...

Keyword-Only Parameters

Keyword-only parameters (referenced in PEP 3102) are parameters that indicate the arguments passed into a function call must be done by keyword only (ie: not by position). The * operator is used in the function definition, indicating that all parameters to the right are keyword-only parameters.

The * operator may be defined once, and, if exists, at least one keyword-only parameter must be defined.

Usage:

  • to be explicit in the function call
  • to prevent function calls being coupled with the order of parameters

Examples:

def f(a, b, *, c):
    ...

Variable-Length Keyword-Only Parameters (**kwargs)

In a function definition, a parameter preceded by a double asterisk (**) indicates argument dictionary packing (the parameter name is commonly called **kwargs). The function accepts a variable number of keyword arguments which will be unpacked as a dictionary.

The ** operator cannot have a default value and no parameters may follow it.

Usage:

  • to allow a variable number of keyword arguments to be passed into the function

Examples:

def f(**kwargs):
    ...

Calling a Function

The grammar of a function call allows for the specification of positional and keyword arguments, and variable-length arguments.

Positional Arguments

Positional arguments (required arguments) are arguments passed in the function call by binding argument values to parameter positions.

Positional arguments must be specified in order, and the number of arguments must match the number of parameters.

Examples:

def f(a, b, c):
    ...
 
f(1, 2, 3)

Variable-Length Positional Arguments

In a function call, an argument preceded by a single asterisk (*) indicates that the argument should be unpacked as a tuple and passed to the function as separate positional arguments. This operator may be applied to any iterable object.

Examples:

def f(a, b, c):
    ...
 
x = (1, 2, 3)
f(*x)

Keyword Arguments

Keyword arguments (named arguments) are arguments passed in the function call by binding argument values to parameter keywords.

Keyword arguments may be specified in any order, and each keyword argument must match a parameter name.

Examples:

def f(a, b, c):
    ...
 
f(a=1, b=2, c=3)

Variable-Length Keyword Arguments

In a function call, an argument preceded by a double asterisk (**) indicates that the argument should be unpacked as a dictionary and passed to the function as separate keyword arguments. This operator may be applied to any mapping object.

Examples:

def f(a, b, c):
    ...
 
x = {'a': 1, 'b': 2, 'c': 3}
f(**x)

Summary

Defining a function:

  • a parameter name may be defined only once
  • required parameters must come before optional parameters for all non keyword-only parameters (ie: everything before the first of either * or **)
  • the / operator indicates that all parameters to the left (with at least one) are positional-only parameters
  • the * operator preceeding a single parameter indicates variable-length positional-only parameter packing
    • the parameter cannot have a default value
  • the * operator indicates that all parameters to the right (with at least one) are keyword-only parameters
  • the ** operator preceeding a single parameter indicates variable-length keyword-only parameter packing
    • the parameter cannot have a default value
  • the /, * and ** operators may each be defined once and must occur in the aforementioned order
  • no parameters may follow the ** operator

Calling a function:

  • positional arguments must come before keyword arguments
  • the order of positional arguments matter
  • the order of keyword arguments does not matter
  • no argument may receive a value more than once
  • all keyword arguments passed must match one of the parameter names accepted by the function
  • the names of positional-only parameters can be used in **kwargs without ambiguity