Positional and Keyword Arguments¶
Traditional Function Call¶
An ordinary function, taking two parameters
a
andb
def f(a, b): print(a, b)
Called with positional arguments
f(1, 2)
1 2
Called with keyword arguments
f(a=3, b=4)
3 4
Supplying Function Arguments Dynamically¶
Positional arguments: sequence
args = [1, 2] f(*args)
1 2
Any sequence is sufficient - e.g.
range()
args = range(1, 3) f(*args)
1 2
Keyword arguments: mapping (usually
dict
)kwargs = {'a':1, 'b':2} f(**kwargs)
1 2
Functions That Takes Arbitrary Number Of Positional Arguments¶
The other way around: not passing parameters dynamically, but accepting them dynamically
“Starargs”:
*args
function parameterargs
is just a common name, can be arbitrary
def f(*args): # <--- starargs
print(args, type(args)) # <--- will print *tuple*
Called traditionally, with positional arguments
Any number of arguments possible
f(1, 2)
f(1, 2, 3)
(1, 2) <class 'tuple'>
(1, 2, 3) <class 'tuple'>
Functions That Take Arbitrary Keyword Arguments¶
Much like positional args, but keyword args and
dict
“Starstarargs”:
**kwargs
function parameterAgain,
kwargs
is just a common name, can be arbitrary
def f(**kwargs): # <--- starstarargs
print(kwargs, type(kwargs)) # <--- will print *dict*
Called traditionally, with keyword arguments
Any number of arguments possible
f(a=1, b=2)
f(a=1, b=2, c=3)
{'a': 1, 'b': 2} <class 'dict'>
{'a': 1, 'b': 2, 'c': 3} <class 'dict'>
And Arbitrary Positional And Keyword Arguments?¶
Rule: positional Arguments must come before keyword arguments
def f(*args, **kwargs):
print(args)
print(kwargs)
f(1, 2, a=3, b=4)
(1, 2)
{'a': 3, 'b': 4}
Ultimate Dynamicity: Arbitrary Positional And Keyword Arguments¶
Pass-through: accept any number and of arguments
Pass them on as they were passed
Typical usecase: decorators
def f(*args, **kwargs):
print(*args, **kwargs)
f(1, 2, end='\n(done)\n') # <--- actually, this *is* print
1 2
(done)
Use Case: A Better print()
¶
Works like
print()
Has a number of bells and whistles of its own
⟶
indent
import sys
def my_print(*args, **kwargs):
indent = kwargs.pop('indent') # <--- remove from kwargs
if indent is not None:
args = (' '*indent,) + args
print(*args, **kwargs) # <--- pass rest to print
my_print(1, 2,
end='\n(done)\n', # <--- consumed by print
indent=4, # <--- consumed by my_print
)
1 2
(done)