Iterating at Once with the Asterisk (*) – Unpacking in Data Science 2026

Data Science Tool Box Mar 18, 2026

Iterating at Once with the Asterisk (*) – Unpacking in Data Science 2026

The asterisk (* and **) is a powerful Python feature for unpacking iterables and dictionaries. In data science, mastering unpacking helps you write cleaner, more concise, and more Pythonic code when working with lists, tuples, function arguments, and data structures.

TL;DR — Asterisk Usage

  • * – Unpacks iterables (lists, tuples, etc.)
  • ** – Unpacks dictionaries (keyword arguments)
  • Very useful in function calls, list creation, and data manipulation

1. Basic Unpacking with *

numbers = [10, 20, 30, 40]

# Unpacking into variables
a, b, *rest = numbers
print(a, b, rest)           # 10 20 [30, 40]

# Using * in function calls
def calculate_total(*values):
    return sum(values)

total = calculate_total(*numbers)
print(total)

2. Common Data Science Use Cases

import pandas as pd

# Create a small demo file so this example runs as-is
# (in your project, sales_data.csv is your real export)
import numpy as np
rng = np.random.default_rng(42)
n = 60
pd.DataFrame({
    "order_id": range(1001, 1001 + n),
    "order_date": pd.date_range("2026-01-01", periods=n, freq="3D"),
    "customer_id": rng.integers(101, 121, n),
    "customer_name": rng.choice([" ana", "ben ", "chen", "dana"], n),
    "product_id": rng.integers(1, 9, n),
    "region": rng.choice(["North", "South", "East", "West"], n),
    "category": rng.choice(["Electronics", "Computers", "Books", "Home"], n),
    "payment_method": rng.choice(["card", "cash", "wallet"], n),
    "segment": rng.choice(["consumer", "business"], n),
    "quantity": rng.integers(1, 6, n),
    "amount": rng.uniform(50, 2500, n).round(2),
    "discount": rng.choice([0.0, 0.05, 0.1, 0.2], n),
}).assign(
    price=lambda d: (d["amount"] / d["quantity"]).round(2),
    profit=lambda d: (d["amount"] * rng.uniform(0.05, 0.3, n)).round(2),
).assign(
    ship_date=lambda d: d["order_date"] + pd.Timedelta(days=2),
    status=lambda d: np.where(d["amount"] > 2000, "priority", "standard"),
).to_csv("sales_data.csv", index=False)

df = pd.read_csv("sales_data.csv")

# 1. Unpacking column names
cols = ["order_date", "customer_id", "amount", "region"]
date_col, id_col, *metric_cols = cols

# 2. Passing multiple arguments to a function
def train_model(*feature_columns):
    print(f"Training with features: {feature_columns}")

train_model(*metric_cols)

# 3. Creating new lists with unpacking
new_features = ["profit", "margin", *metric_cols]
print(new_features)

3. Advanced Unpacking with ** (Dictionary Unpacking)

model_params = {
    "n_estimators": 200,
    "max_depth": 10,
    "random_state": 42
}

# Unpacking dictionary as keyword arguments
def train_random_forest(**kwargs):
    print("Training with parameters:")
    for key, value in kwargs.items():
        print(f"  {key}: {value}")

train_random_forest(**model_params)

4. Best Practices in 2026

  • Use * to unpack iterables when calling functions or creating new lists
  • Use ** to unpack dictionaries as keyword arguments
  • Combine with enumerate() and zip() for powerful one-liners
  • Use *rest to capture remaining elements when unpacking
  • Keep unpacking readable — avoid excessive complexity in one line

Unpacking with the Asterisk

A single asterisk unpacks an iterable into separate items. In a function call, print(*values) passes each item as its own argument. In an assignment, first, *rest = values collects the remaining items into a list.

Two asterisks do the same for dictionaries in function calls and dictionary literals: f(**options) passes key-value pairs as keyword arguments, and {**defaults, **overrides} merges dictionaries, with later keys winning.

These forms are concise ways to combine lists, pass configuration and split records without index arithmetic.

Worked Example: Splitting, Merging and Passing

We split a record, combine lists, merge settings and pass them to a function.

record = ["2026-01-05", "North", 120, 95, 130]
date, region, *daily_sales = record
print(date, region, daily_sales)

first, *_, last = daily_sales
print(first, last)

combined = [*daily_sales, *[110, 140]]
print(combined)

defaults = {"sep": ",", "decimal": "."}
overrides = {"sep": ";"}
settings = {**defaults, **overrides}
print(settings)

def describe(sep, decimal):
    return f"sep={sep!r} decimal={decimal!r}"
print(describe(**settings))

The starred name always receives a list, even if it is empty. In the merged settings, the semicolon from overrides replaces the default comma because later keys win.

Common Mistakes

  • Using more than one starred name in one assignment.
  • Expecting a starred target to be a tuple rather than a list.
  • Passing ** with keys that do not match parameter names.
  • Forgetting that dictionary merge order decides which value wins.

Quick Summary

  • *iterable unpacks items in calls and literals.
  • first, *rest = seq splits sequences.
  • **dict passes keyword arguments and merges dicts.
  • Later keys win when merging.

Conclusion

The asterisk operators (* and **) are powerful tools for unpacking data in Python. In data science, they help you write cleaner code when passing column lists to functions, creating new feature sets, and handling configuration parameters. When used appropriately, unpacking makes your code more concise and Pythonic while maintaining readability.

Next steps:

  • Review your current code and look for opportunities to use * and ** unpacking to simplify function calls and list/dict operations

Related Tutorials

Share:
Last updated: March 2026
Built-in Functions in Python 2026 str() in Python 2026: String Conversion + Modern Formatting & Best Practices memoryview with JAX in Python 2026: Zero-Copy NumPy → JAX Array Interop + Efficient ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + GPU Pinning & ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + ML Examples memoryview with NumPy & PyTorch in Python 2026: Zero-Copy Views, Efficient Slicing & ML Interop Examples memoryview with NumPy in Python 2026: Zero-Copy Views, Efficient Slicing & Real ML Examples memoryview() in Python 2026: Zero-Copy Magic for Large Binary Data + Real Examples import() in Python 2026: How It Works, Security Risks & Modern Alternatives (importlib) zip() in Python 2026: How to Use It, strict=True Behavior & Real-World Examples vars() in Python 2026: Accessing Object Namespace + Modern Introspection Patterns type() in Python 2026: Dynamic Type Inspection & Object Creation + Modern Patterns tuple() in Python 2026: Immutable Sequences + Modern Patterns & Best Practices super() in Python 2026: Method Resolution & Modern Inheritance Patterns sum() in Python 2026: Summing Iterables + Modern Numeric Patterns & Best Practices staticmethod() in Python 2026: Static Methods, Utility Functions & Modern Best Practices sorted() in Python 2026: Sorting Iterables + Modern Patterns & Best Practices slice() in Python 2026: Creating Slice Objects + Modern Patterns & Best Practices setattr() in Python 2026: Dynamic Attribute Setting + Modern Patterns & Safety set() in Python 2026: Mutable Sets Creation + Modern Patterns & Best Practices