Function Arguments: Positional, Keyword, Default, and Variable-Length
When calling functions, you can pass input values known as arguments to the function’s parameters. Python functions support several ways to pass arguments:
Positional Arguments: These are the most common way to pass values to parameters. You provide the arguments in the same order as the function’s parameter list. Each argument is assigned to the corresponding parameter by position. For example, in greet("Alice", 21), "Alice" is assigned to the first parametername, and 21 the second parameter age. The order matters with positional arguments. If a function has multiple parameters without default values, you must pass arguments for each, in the correct sequence.
Keyword Arguments: Python also allows you to specify arguments by the parameter name, using the form param=value when calling the function. In this case, the order of arguments doesn’t matter, because each is matched by name. For instance, the The greet function defined earlier could be called as greet(age=21, name="Alice") and it would have the same effect as before, explicitly assigning name="Alice" and age=21. Keyword arguments must follow any positional arguments in a function call. This means you can’t provide a positional argument after you’ve started providing keywords. All keywords used must correspond to parameters in the function definition, and no parameter should receive a value more than once. For example, calling greet("Alice", name="Bob") would produce an error because the name parameter is given a value twice (once positionally as "Alice" and once as "Bob").
Default Arguments: A function can specify default values for certain parameters. These parameters become optional — the caller can omit them and the default will be used. You define a default by using the syntax param=value in the function definition. For example:
def power(base, exponent=2):
return base ** exponent
Here, exponent has a default value of 2. You can call power(5) With just one argument, and it will assume the exponent 2 (returning 25); or you can override the default by calling power(5, 3) to get 125. Default values are evaluated at function definition time, not at call time. This means if you use a mutable object (like a list or dict) as a default, that same object is reused across calls, which can lead to surprising behaviour. For instance, using a list as a default parameter will accumulate changes between calls. It’s generally safer to use immutable types or None as defaults and handle mutable initialisation inside the function. Important to note: if a function has some parameters with defaults and some without, the ones without a default (required params) must come first in the definition. When calling, you can choose to omit some arguments if their parameters have defaults, but you cannot skip a required parameter.
Variable-Length Arguments: Sometimes you want a function to accept an arbitrary number of arguments. Python provides special syntax for this: use * to pack positional variable arguments and ** to pack keyword variable arguments. In the function definition, *args will collect any extra positional arguments passed by the caller into a tuple named args, and **kwargs will collect any extra keyword arguments into a dictionary named kwargs. For example:
def example(*args, **kwargs):
print("Positional arguments (tuple):", args)
print("Keyword arguments (dict):", kwargs)
example(10, 20, 30, color="blue", size="M")
Output:
Positional arguments (tuple): (10, 20, 30)
Keyword arguments (dict): {'color': 'blue', 'size': 'M'}
In this call, 10, 20, 30 were packed into the args tuple, and the named arguments were packed into the kwargs dictionary. Inside the function, you can iterate over args or kwargs to handle an arbitrary number of inputs. The usage of *args and **kwargs is common for functions that need to accept flexible arguments. Python’s standard library uses this in many places. For instance, a famous illustration is:
def cheeseshop(kind, *arguments, **keywords):
print("-- Do you have any", kind, "?")
print("-- I'm sorry, we're all out of", kind)
for arg in arguments:
print(arg)
print("-" * 40)
for kw in keywords:
print(kw, ":", keywords[kw])
# Calling the function with various extra arguments:
cheeseshop("Limburger", "It's very runny, sir.", "It's really very, VERY runny, sir.",
shopkeeper="Michael Palin", client="John Cleese", sketch="Cheese Shop Sketch")
In this call, "Limburger" is mapped to the first parameter kind, two extra string arguments are collected in arguments, and three keyword arguments are collected in keywords. The function prints a dialog, then iterates through the arguments tuple and keywords dict to print them. The output (abridged) would be:
-- Do you have any Limburger ?
-- I'm sorry, we're all out of Limburger
It's very runny, sir.
It's really very, VERY runny, sir.
----------------------------------------
shopkeeper : Michael Palin
client : John Cleese
sketch : Cheese Shop Sketch
As seen above, the variable-length parameters allow the function to handle any number of extra arguments gracefully. Note that if you use *args and **kwargs in the function signature, they should come after any regular parameters (and *args must come before **kwargs). Also, Python allows combining regular, default, * and ** parameters in advanced ways (including keyword-only or positional-only parameters using special markers), but those are more advanced features beyond our current scope.
Summary: With these argument passing techniques, you have flexibility in how you call functions. Positional arguments are simple but fixed-order; keyword arguments add clarity and can skip optional parameters; default arguments provide fallback values; and *args/**kwargs Let you design functions that accept a variable number of inputs. Always ensure that the way you call a function matches its definition. If you mix argument types, remember the rule that positional arguments come first, followed by keyword arguments.
