Iterating at once with the asterisk (*) is one of Python’s most elegant and powerful features — it lets you unpack (or “splat”) the elements of an iterable in a single step. The asterisk operator (*) takes everything inside a list, tuple, set, or other iterable and spreads those elements out — either into function arguments, new collections, or unpacking assignments. It’s a clean, concise way to handle iterables without explicit loops in many common cases.
In 2026, the * operator (often called “splat” or “unpack”) remains essential — used constantly for function calls, list/tuple/set creation, merging iterables, and unpacking assignments. Here’s a complete, practical guide to using * for iteration and unpacking — with real patterns, best practices, and modern tips.
Start with the most common use: passing all elements of an iterable as separate positional arguments to a function. The * unpacks the iterable in one go — no need to loop or index manually.
def print_fruits(fruit1: str, fruit2: str, fruit3: str) -> None:
"""Print three fruits."""
print(fruit1)
print(fruit2)
print(fruit3)
fruits = ["apple", "banana", "cherry"]
print_fruits(*fruits) # Unpacks list into 3 separate arguments
# Output:
# apple
# banana
# cherry
Another everyday pattern: creating a new list, tuple, or set by copying or combining iterables — the * unpacks elements instantly.
fruits = ["apple", "banana", "cherry"]
# Copy list
new_list = [*fruits] # ['apple', 'banana', 'cherry']
# Merge multiple iterables
more_fruits = ["date", "elderberry"]
combined = [*fruits, *more_fruits] # ['apple', 'banana', 'cherry', 'date', 'elderberry']
# Create tuple or set
fruit_tuple = (*fruits,) # ('apple', 'banana', 'cherry')
fruit_set = {*fruits, "banana"} # {'apple', 'banana', 'cherry'} (duplicates removed)
Unpacking assignments let you split iterables into variables — very useful for splitting pairs, coordinates, or return values.
point = (10, 20)
x, y = *point, # Unpack tuple into x and y ? x=10, y=20
name, age, city = "Alice", 30, "New York"
print(name, age, city) # Alice 30 New York
# Unpack first and rest
first, *rest = [1, 2, 3, 4, 5]
print(first, rest) # 1 [2, 3, 4, 5]
Real-world pattern: merging dictionaries, combining lists from multiple sources, or passing variable arguments to functions like print(), max(), or sum().
dict1 = {"a": 1, "b": 2}
dict2 = {"c": 3, "d": 4}
merged = {**dict1, **dict2} # {'a': 1, 'b': 2, 'c': 3, 'd': 4}
numbers = [1, 2, 3]
print(*numbers) # 1 2 3 (unpacks into separate print arguments)
print(max(*numbers)) # 3
print(sum(*numbers)) # 6 (but sum() prefers iterable directly — sum(numbers))
Best practices make * unpacking safe, readable, and efficient. Use * for unpacking positional arguments — it’s clearer than manual loops. Prefer ** for merging dictionaries — since Python 3.9+, you can also use dict union |= or {**d1, **d2}. When unpacking, match the number of variables to the iterable length — or use *rest to capture extras. Avoid over-unpacking large iterables in memory-constrained code — prefer generators or lazy iteration. Modern tip: use * unpacking with type hints — def func(*args: int) or def func(**kwargs: str) — improves clarity and mypy checks. In production, be cautious with **kwargs — they can hide required arguments; prefer explicit parameters when possible. Combine * with zip(*lists) for transposing data (turning rows into columns).
The asterisk (*) is Python’s clean way to say “take everything inside this iterable and spread it out.” In 2026, use it for function calls, merging collections, unpacking assignments, and creating copies — it makes code shorter, clearer, and more expressive. Master * unpacking, and you’ll handle iterables with elegance and efficiency.
Next time you need to pass, merge, copy, or split an iterable — reach for *. It’s one of Python’s most powerful and Pythonic operators.