Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

* and ** expand values in different ways. In a function call, *iterable turns each item into a positional argument, while **mapping turns each key-value pair into a keyword argument. The same notation also appears in assignments, list displays and dictionary displays, where it has related but distinct behavior.

What the operators mean

Think of unpacking as removing one container layer. A list, tuple or other iterable can be spread into individual values with *. A dictionary or other mapping can be spread into named entries with **. The surrounding Python construct determines what those values become.

Context Syntax Operand required Result
Function call func(*items) Iterable Separate positional arguments
Function call func(**options) Mapping Keyword arguments
Assignment first, *rest = values Iterable rest receives a list of remaining items
List display [*items] Iterable Items inserted into a new list
Dictionary display {**options} Mapping Entries inserted into a new dictionary

The Python tutorial documents argument-list unpacking and display forms at docs.python.org/3/tutorial/controlflow.html, while the language reference specifies expression and dictionary-display rules at docs.python.org/3/reference/expressions.html.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Unpack positional arguments with *

Calling a function from a list or tuple

Use a single star when the function expects separate positional parameters but your values are already grouped in an iterable.

def make_point(x, y):
    return {"x": x, "y": y}

coords = (3, 8)
point = make_point(*coords)
print(point)  # {'x': 3, 'y': 8}

make_point(*coords) is equivalent to make_point(3, 8). Python iterates over coords and supplies each item in order.

Matching arity matters

The number of unpacked values must fit the callable’s positional parameters, subject to its default and variadic arguments.

def add(a, b):
    return a + b

values = [2, 4]
print(add(*values))       # 6

# add([2, 4])             # TypeError: one list argument, not two numbers
# add(*[1, 2, 3])         # TypeError: too many positional arguments

An integer is not iterable, so add(*5) raises TypeError: argument after * must be an iterable, not int. Wrap a single value in a tuple or list if that is what the API requires.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Combining ordinary and unpacked arguments

def report(name, *scores):
    return name, scores

scores = [91, 88, 95]
print(report("Mina", *scores))  # ('Mina', (91, 88, 95))

Regular positional arguments and starred iterables can be mixed. Evaluation follows the call expression’s order.

Unpack keyword arguments with **

Passing dictionary keys as parameter names

Use two stars when a mapping’s keys correspond to the function’s keyword parameters.

def parrot(voltage, state="a stiff", action="voom"):
    print(voltage, state, action)

options = {"voltage": "four million", "state": "stable"}
parrot(**options)
# four million stable voom

This is equivalent to parrot(voltage="four million", state="stable"). Every key must be a valid keyword accepted by the function. A misspelled key produces an unexpected-keyword TypeError.

Combining positional and keyword expansion

def connect(host, port, secure=False):
    return host, port, secure

address = ("example.com", 443)
flags = {"secure": True}
print(connect(*address, **flags))

Do not provide the same parameter twice. For example, connect("example.com", *[443], port=8443) raises a multiple-values error for port.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Definitions versus calls

The spelling looks similar in a function definition but reverses the operation. In a definition, *args collects extra positional arguments into a tuple and **kwargs collects extra keyword arguments into a dictionary.

def log_event(event, *args, **kwargs):
    print(event)
    print(args)    # tuple of extra positional values
    print(kwargs)  # dictionary of extra named values

log_event("upload", "image.png", retry=True)

At a call site, * and ** expand existing containers; in a definition they collect arguments supplied by the caller.

Starred assignment targets

Extended iterable unpacking lets one assignment target absorb any number of middle items. The starred target is always a list, even when the source is a tuple or generator.

values = [10, 20, 30, 40]
first, *middle, last = values
print(first)   # 10
print(middle)  # [20, 30]
print(last)    # 40

Beginning, middle and end forms

*start, last = [1, 2, 3]
# start == [1, 2], last == 3

first, *rest = [1, 2, 3]
# first == 1, rest == [2, 3]

first, *nothing, last = [7, 9]
# nothing == []

There can be only one starred target in a single unpacking assignment because Python must know how to divide the remaining items. The non-starred targets still require enough values; otherwise Python raises ValueError.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Any iterable can be unpacked

def numbers():
    yield 4
    yield 5
    yield 6

first, *rest = numbers()
print(first, rest)  # 4 [5, 6]

The iterable is consumed to create the list for the starred target. Be careful with large or infinite iterators: collecting the remainder can use substantial memory or never finish.

Unpacking in list displays

A starred expression inside a list contributes each item to the new list rather than adding the source iterable as one nested element.

items = ["start", *range(3), "end"]
print(items)  # ['start', 0, 1, 2, 'end']

left = [1, 2]
right = [3, 4]
combined = [*left, *right]

This is useful for concatenating iterables while keeping fixed values visible. The operand must be iterable; [*42] raises TypeError. Unlike left + right, display unpacking also works naturally with generators and other iterable types.

Unpacking in dictionary displays

Two stars in a dictionary display copy key-value pairs into a new dictionary.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
defaults = {"color": "blue", "count": 8}
overrides = {"color": "yellow"}
combined = {**defaults, **overrides}
print(combined)  # {'color': 'yellow', 'count': 8}

Later entries win

When keys collide, the entry appearing later in the display replaces the earlier value. This makes the defaults-then-overrides pattern explicit.

base = {"timeout": 10, "retries": 2}
per_request = {"timeout": 30}
config = {**base, **per_request}

The operation creates a new dictionary; it does not mutate either source. The operand must be a mapping, so {**[('a', 1)]} fails even though the list contains pairs. Use dict([('a', 1)]) first when necessary.

Multiple mappings and ordinary entries

user = {"name": "Ari"}
record = {"id": 17, **user, "active": True}

Dictionary-display unpacking was added in Python 3.5 through the work proposed by PEP 448, as described in the language reference. It is available in supported Python 3 versions.

Choosing the right form

Question Use Example
Does a callable need positional values? * at the call site range(*limits)
Does a callable need named values? ** at the call site request(**params)
Do you need the first/last item plus the remainder? Starred assignment target head, *tail = data
Do you need one flat list? * in a list display [*a, *b]
Do you need defaults overridden? ** in a dictionary display {**defaults, **custom}

Common errors and fixes

  • “Argument after * must be an iterable.” The value is not iterable. Pass a list, tuple, string or other iterable, or remove the star for a single scalar.
  • “Argument after ** must be a mapping.” Use a dictionary or mapping object, not a list of pairs or a scalar.
  • Unexpected keyword argument. Check that every dictionary key exactly matches a parameter name and that the function accepts it.
  • Multiple values for an argument. A parameter was supplied positionally and by keyword. Supply it once.
  • Not enough or too many values to unpack. Count fixed assignment targets and remember that only one starred target may absorb the remainder.
  • Unexpected overwrite in a merged dictionary. Inspect display order; later duplicate keys always win.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, evaluation and compatibility

Unpacking is generally a clarity feature, not a promise of zero-copy behavior. A list display and dictionary display create new containers, and a starred assignment creates a new list for its remainder. Function-call expansion may iterate through the operand before invocation. For very large data, consider whether a streaming interface or direct iteration is more appropriate.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Extended iterable unpacking arrived in Python 3.0 under PEP 3132; the Python 3.0 notes record that the collected target is always a list: docs.python.org/3.10/whatsnew/3.0.html. Dictionary-display unpacking requires Python 3.5 or newer. These operators are separate grammar features from typing syntax, so consult version-specific typing documentation when stars appear in annotations.

Or skip the browser setup

If you are generating documentation or other visual assets from web pages, ScreenshotNeo provides a single-call screenshot API and MCP server. It accepts cookie and consent banners before capture, removes more than 60 known consent platforms plus newsletter popups and chat widgets, and bills only clean shots. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed; each response identifies the result with X-Page-Verdict and X-Billed headers.

For a quick capture, see the ScreenshotNeo API documentation:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

The same request in Python:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

And in Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);

ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients. Every plan includes features such as full-page and selector capture, device presets, custom CSS and JavaScript, waits, request blocking, headers and cookies, geolocation, PDF options, caching, signed links, asynchronous jobs and bulk capture of up to 100 URLs per call. The Free plan includes 1,000 screenshots each month without a card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

FAQ

Can I use both * and ** in one call?

Yes. Use * for positional values and ** for keyword values, provided they do not assign the same parameter twice.

Does starred assignment preserve the source type?

No. The starred target is always a list, regardless of whether the source is a tuple, list, string or generator.

Do dictionary unpacking operations modify the original dictionaries?

No. A dictionary display creates a new dictionary; duplicate keys are resolved according to display order.

Frequently Asked Questions

Can a function call unpack a set with *?

Yes, because a set is iterable, but its iteration order is not a reliable positional order. Use an ordered sequence when argument positions matter.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why does ** accept dictionaries but not ordinary lists?

Keyword expansion needs key-value pairs addressed by parameter names, so Python requires a mapping. Convert suitable pair data to a dictionary first.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.