Fundamentals 10 min read

Master Python’s Unpacking Operators: * and ** for Lists, Dictionaries, and Functions

This guide explores Python’s unpacking operators * and **, showing how they simplify printing, assigning, merging lists and dictionaries, handling variable function arguments, creating dynamic logging functions, and performing nested unpacking, while also offering practical tips to avoid common pitfalls.

Code Mala Tang
Code Mala Tang
Code Mala Tang
Master Python’s Unpacking Operators: * and ** for Lists, Dictionaries, and Functions

Today I want to share my experience using unpacking operators — * for sequences, ** for dictionaries.

What is the unpacking operator?

These operators help quickly unpack lists, tuples, and dictionaries. I mainly use * for sequences and ** for dictionaries.

Unpacking lists and tuples

Before learning the * operator, I usually used a loop to print each element, for example:

<code>numbers = [1, 2, 3, 4]
for num in numbers:
    print(num)
</code>

Now I can accomplish the same with a single line of code:

<code>numbers = [1, 2, 3, 4]
print(*numbers)
</code>

The output is:

<code>1 2 3 4
</code>

This makes the code more concise.

Understanding this — unpacking is not only for printing; it can also be used in assignment. I can split a list into multiple parts with a single line of code, which is amazing, right?

For example:

<code>first, *middle, last = [1, 2, 3, 4, 5]
</code>

The output is:

<code>first = 1
middle = [2, 3, 4]
last = 5
</code>

In this example, first takes the first element, last takes the last element, and middle captures all the middle elements. This technique is very useful when we need to split data into multiple parts.

Merging lists using unpacking

We often need to merge lists. Previously I usually used the + operator, for example:

<code>list1 = [1, 2, 3]
list2 = [4, 5, 6]
merged = list1 + list2
print(merged)
</code>

But using unpacking operators, this process becomes more flexible:

<code>list1 = [1, 2, 3]
list2 = [4, 5, 6]
merged = [0, *list1, *list2, 7]
print(merged)
</code>

The output is:

<code>[0, 1, 2, 3, 4, 5, 6, 7]
</code>

Now I can easily add extra elements while merging, giving me more flexible control over the data.

Merging dictionaries using **

Previously I merged dictionaries like this:

<code>dict1 = {"a": 1, "b": 2}
dict2 = {"c": 3, "d": 4}
merged = dict1.copy()
merged.update(dict2)
print(merged)
</code>

Now I can merge with a single line of code:

<code>dict1 = {"a": 1, "b": 2}
dict2 = {"c": 3, "d": 4}
merged = {**dict1, **dict2}
print(merged)
</code>

Note that if the dictionaries share the same key, the value from the second dictionary overwrites the first, which helps understand which values are retained during merging.

Using unpacking operators in function calls

We often write functions whose number of parameters may vary. Using unpacking operators, I can pass any number of arguments without extra hassle.

Using *args

Now I usually use *args when I'm unsure how many positional arguments a function may need. For example:

<code>def add_numbers(*args):
    total = sum(args)
    print("Total:", total)

add_numbers(1, 2, 3, 4)
</code>

This makes the function very flexible. I can pass any number of numbers without modifying the function.

Using **kwargs

Similarly, ** lets me handle named parameters. This is perfect when I need to add extra options to a function:

<code>def greet(name, **kwargs):
    greeting = kwargs.get("greeting", "Hello")
    punctuation = kwargs.get("punctuation", "!")
    print(f"{greeting}, {name}{punctuation}")

greet("Kiran", greeting="Hi", punctuation="!!!")
</code>

Now I can pass extra information, and the function extracts what it needs, making calls cleaner.

Implementing dynamic function parameters with unpacking operators

I recall writing a logging function that needed many optional parameters without cluttering the code. In this case, unpacking operators were a great help:

<code>def log_message(message, **options):
    level = options.get("level", "INFO")
    timestamp = options.get("timestamp", "N/A")
    extra = options.get("extra", "")
    print(f"[{level}] {timestamp}: {message}{extra}")

log_message("System started.", level="DEBUG", timestamp="2025-03-01 10:00", extra="Initialization complete.")
</code>

In this way, my logging function can be adjusted according to different needs.

Nested unpacking

Python supports nested unpacking, which is useful for handling complex data structures.

For example:

<code>data = [("Kiran", 25), ("Mann", 30), ("Grewal", 35)]
for name, age in data:
    print(f"{name} is {age} years old.")
</code>

I can also mix unpacking in more complex structures, for example:

<code>records = [("Kiran", [85, 90, 95]), ("Mann", [70, 80, 90])]
for name, scores in records:
    first, *middle, last = scores
    print(f"{name}'s first score: {first}, last score: {last}, other scores: {middle}")
</code>

The output is:

<code>Kiran's first score: 85, last score: 95, other scores: [90]
Mann's first score: 70, last score: 90, other scores: [80]
</code>

Using unpacking for function parameters

When a function returns multiple values, I use unpacking to store them in separate variables:

<code>def get_stats(numbers):
    total = sum(numbers)
    count = len(numbers)
    average = total / count if count else 0
    return total, count, average

total, count, average = get_stats([10, 20, 30, 40])
print("Total:", total, "Count:", count, "Average:", average)
</code>

The output is:

<code>Total: 100 Count: 4 Average: 25.0
</code>

This makes the code easier to read and maintain.

Things to watch out for when using

Although I like using these operators, I use them cautiously. Keep the following points in mind:

Do not use too many unpacking operators in a single line, as it can make the code hard to read. Always ask if others can understand it easily.

When merging dictionaries, if the same key appears in multiple dictionaries, the value from the last dictionary overwrites earlier ones. Check for potential conflicts when needed.

Ensure the data format being unpacked matches expectations, otherwise the code may crash.

Pythoncode examplesfunction-argumentsunpackingstar-operatordictionary-merge
Code Mala Tang
Written by

Code Mala Tang

Read source code together, write articles together, and enjoy spicy hot pot together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.