*args / **kwargs
In Python, *args accepts any number of positional arguments as a tuple, and **kwargs accepts any number of keyword arguments as a dictionary. When combining both, the argument order (regular args → *args → keyword-only args → **kwargs) must be followed. On the caller side, lists and dictionaries can be unpacked with *list and **dict.
Syntax
# *args: accepts any number of positional arguments as a tuple
def func_name(*args):
for item in args:
print(item)
# **kwargs: accepts any number of keyword arguments as a dictionary
def func_name(**kwargs):
for key, value in kwargs.items():
print(key, value)
# Combined (order matters)
def func_name(regular_arg, *args, keyword_only_arg, **kwargs):
pass
# Unpacking on the caller side
func_name(*my_list) # expands a list as positional arguments
func_name(**my_dict) # expands a dict as keyword arguments
Argument Order Rules
| Order | Type | Example | Notes |
|---|---|---|---|
| 1 | Regular positional args | def f(a, b): | Fixed positional arguments. Must come before *args. |
| 2 | Variable positional args | def f(*args): | Accepts any number of positional arguments as a tuple. |
| 3 | Keyword-only args | def f(*args, key): | Arguments after *args can only be passed as keyword arguments. |
| 4 | Variable keyword args | def f(**kwargs): | Accepts any number of keyword arguments as a dictionary. Must be last. |
| - | Caller: * unpacking | f(*my_list) | Expands a list or tuple as positional arguments. |
| - | Caller: ** unpacking | f(**my_dict) | Expands a dictionary as keyword arguments. |
Sample Code
The basics of receiving any number of positional arguments as a tuple with *args.
basic_args.py
# A function that receives a list of PSYCHO-PASS Enforcers using *args.
# Any number of arguments can be received as a tuple.
def list_enforcers(*args):
print("Enforcer list (" + str(len(args)) + " members)")
for i, name in enumerate(args, 1):
print(" " + str(i) + ". " + name)
# Any number of arguments can be passed freely.
list_enforcers("Kogami Shinya")
print("---")
list_enforcers("Kunizuka Yayoi", "Shimomura Mika", "Hinakawa Sho")
print("---")
# The contents of *args is a tuple.
def show_args_type(*args):
print(type(args), args)
show_args_type("Tsunemori Akane", "Ginoza Nobuchika", "Masaoka Tomomi")
python3 basic_args.py
Enforcer list (1 members)
1. Kogami Shinya
---
Enforcer list (3 members)
1. Kunizuka Yayoi
2. Shimomura Mika
3. Hinakawa Sho
---
<class 'tuple'> ('Tsunemori Akane', 'Ginoza Nobuchika', 'Masaoka Tomomi')
The basics of receiving any number of keyword arguments as a dictionary with **kwargs.
basic_kwargs.py
# A function that receives an Inspector's profile using **kwargs.
# Key-value pairs are received together as a dictionary.
def show_profile(**kwargs):
print("Profile information:")
for key, value in kwargs.items():
print(" " + key + ": " + str(value))
# The caller can freely decide the keyword names and count.
show_profile(name="Tsunemori Akane", division="Division 1", role="Inspector")
print("---")
show_profile(name="Ginoza Nobuchika", coefficient=99, hue="Clear")
# The contents of **kwargs is a dictionary.
def show_kwargs_type(**kwargs):
print(type(kwargs), kwargs)
show_kwargs_type(name="Makishima Shogo", status="Wanted")
python3 basic_kwargs.py
Profile information:
name: Tsunemori Akane
division: Division 1
role: Inspector
---
Profile information:
name: Ginoza Nobuchika
coefficient: 99
hue: Clear
<class 'dict'> {'name': 'Makishima Shogo', 'status': 'Wanted'}
Combining regular args, *args, keyword-only args, and **kwargs. The argument order rule must be followed.
combined_args.py
# A function combining multiple argument types.
# Order: regular args -> *args -> keyword-only args -> **kwargs
def register_case(division, *suspects, priority, **details):
print("[Case Registration]")
print(" Division: " + division)
print(" Priority: " + priority) # keyword-only arg
print(" Suspects: " + str(suspects)) # tuple
print(" Details:")
for key, value in details.items():
print(" " + key + ": " + str(value))
# division is positional, priority is keyword-only (must pass as keyword)
register_case(
"Division 1", # division (regular positional arg)
"Makishima Shogo", "Kijima Hiroto", # *suspects (variable positional args)
priority="High", # keyword-only arg
area="Shibuya", # **details
weapon="Hyper-Oratrio",
)
python3 combined_args.py
[Case Registration]
Division: Division 1
Priority: High
Suspects: ('Makishima Shogo', 'Kijima Hiroto')
Details:
area: Shibuya
weapon: Hyper-Oratrio
Unpacking with *list and **dict on the caller side.
unpack_call.py
# A function that receives Dominator configuration.
def configure_dominator(user, mode, coefficient):
print(user + " / Mode: " + mode + " / Coefficient: " + str(coefficient))
# Unpack a list with * and pass as positional arguments.
params = ["Ginoza Nobuchika", "Paralyzer", 180]
configure_dominator(*params)
# Unpack a dict with ** and pass as keyword arguments.
settings = {"user": "Kogami Shinya", "mode": "Lethal Eliminator", "coefficient": 320}
configure_dominator(**settings)
# The same works when passing to a function that accepts *args.
def scan_all(*names):
for name in names:
print(name + "'s hue is being scanned...")
officers = ["Tsunemori Akane", "Kunizuka Yayoi", "Shimomura Mika"]
scan_all(*officers) # each element of the list is expanded as a positional argument.
python3 unpack_call.py Ginoza Nobuchika / Mode: Paralyzer / Coefficient: 180 Kogami Shinya / Mode: Lethal Eliminator / Coefficient: 320 Tsunemori Akane's hue is being scanned... Kunizuka Yayoi's hue is being scanned... Shimomura Mika's hue is being scanned...
Common Mistakes
Common Mistake 1: Reversed order of *args and **kwargs causes SyntaxError
Writing **kwargs before *args causes a SyntaxError. The correct order is: regular args → *args → keyword-only args → **kwargs.
ng_order.py
# NG: writing **kwargs before *args causes a SyntaxError.
def show_info(**kwargs, *args):
pass
python3 ng_order.py
File "ng_order.py", line 2
def show_info(**kwargs, *args):
^
SyntaxError: arguments cannot follow var-keyword argument
ok_order.py
# OK: write in order: regular args -> *args -> **kwargs.
def show_info(*args, **kwargs):
print("args:", args)
print("kwargs:", kwargs)
show_info("Kogami Shinya", "Tsunemori Akane", division="Division 1", role="Inspector")
python3 ok_order.py
args: ('Kogami Shinya', 'Tsunemori Akane')
kwargs: {'division': 'Division 1', 'role': 'Inspector'}
Common Mistake 2: Mixing default-value args with *args
Default-value arguments must be written before *args. Arguments with default values written after *args become keyword-only arguments. Attempting to pass them as positional arguments causes them to be absorbed by *args.
ng_default_args.py
# NG: a default-value argument after *args cannot be passed positionally.
def register(*names, division="Unknown"):
for name in names:
print(name, "->", division)
# Passing division without a keyword causes it to be absorbed into *names.
register("Kunizuka Yayoi", "Shimomura Mika", "Division 1") # "Division 1" ends up in names.
python3 ng_default_args.py Kunizuka Yayoi -> Unknown Shimomura Mika -> Unknown Division 1 -> Unknown
ok_default_args.py
# OK: pass arguments after *args using keywords.
def register(*names, division="Unknown"):
for name in names:
print(name, "->", division)
register("Kunizuka Yayoi", "Shimomura Mika", division="Division 1")
python3 ok_default_args.py Kunizuka Yayoi -> Division 1 Shimomura Mika -> Division 1
Common Mistake 3: Passing the same key twice to **kwargs causes SyntaxError
Passing the same key name twice to **kwargs causes a SyntaxError. The same issue occurs when a dict unpacking and a normal keyword argument share the same name.
ng_duplicate_key.py
# NG: passing the same key twice causes a SyntaxError.
def show_profile(**kwargs):
print(kwargs)
# Writing the same keyword argument twice causes SyntaxError.
show_profile(name="Tsunemori Akane", name="Ginoza Nobuchika")
python3 ng_duplicate_key.py
File "ng_duplicate_key.py", line 6
show_profile(name="Tsunemori Akane", name="Ginoza Nobuchika")
^^^^
SyntaxError: keyword argument repeated: name
ok_duplicate_key.py
# OK: make sure keys do not duplicate.
def show_profile(**kwargs):
print(kwargs)
show_profile(name="Tsunemori Akane", division="Division 1", role="Inspector")
python3 ok_duplicate_key.py
{'name': 'Tsunemori Akane', 'division': 'Division 1', 'role': 'Inspector'}
Notes
The names args and kwargs themselves have no special meaning — the * and ** symbols are what matter. They are simply widely used by convention, so *values or **options works just as well. The convention of using *args and **kwargs has become established for readability.
Violating the argument order rules causes a SyntaxError. The correct order is: regular positional args → *args → keyword-only args → **kwargs. Arguments written after *args automatically become keyword-only, meaning the caller must always pass them by keyword. This property can also be used by writing just * without *args as a separator for keyword-only arguments (see def / Function Definition).
The * and ** unpacking on the caller side allows passing parameters stored in lists or dicts directly to functions, making them useful for passing configuration data and implementing wrapper functions. The pattern of forwarding received **kwargs to another function using **kwargs is also frequently seen in decorator implementations.
If you find any errors or copyright issues, please contact us.