What is ** in Python? (Double Asterisk or Double Star)

double asterisk in python

Python is known for its simplicity and flexibility, which is why it’s a popular programming language for beginners and experts alike. One of the operators you’ll often encounter is ** in Python. It serves multiple purposes and is a powerful tool when you know how to use it.

In this article, we’ll explore the different uses of the ** operator in Python with easy-to-understand examples.

What is ** in Python?

The ** (Double asterisk or Double star)operator in Python is used for two main purposes:

  • Exponentiation (raising a number to a power)
  • Unpacking keyword arguments into functions

Let’s dive deeper into both of these usages and understand how they work with practical examples.

**Exponentiation Using ** in Python

The first and most common use of ** in Python is for exponentiation. Simply put, ** allows you to raise a number to the power of another number.

Syntax:

base ** exponent

Example:

result = 2 ** 3  # 2 raised to the power of 3
print(result)    # Output: 8

In this example, 2 ** 3 means 23, which equals 8.

Exponentiation with Complex Numbers

Python also supports complex numbers, and you can use the ** operator with them too!

complex_number = (2 + 3j) ** 2
print(complex_number)  # Output: (-5+12j)

In this case, (2 + 3j)2 results in the complex number (-5 + 12j).

Right-to-Left Associativity

The ** operator in Python is right-associative. This means if you have multiple exponentiation operations in a row, Python evaluates them from right to left.

result = 2 ** 3 ** 2
print(result)  # Output: 512

Here, Python evaluates 3 ** 2 first, which gives 9, and then 2 ** 9, which results in 512.

**Unpacking Keyword Arguments with ** in Python

Another important use of ** is for unpacking dictionaries into keyword arguments when calling functions. This allows you to pass key-value pairs stored in a dictionary as arguments to a function.

Example:

def greet(name, age):
    print(f"Hello, {name}. You are {age} years old.")

person = {'name': 'Alice', 'age': 30}
greet(**person)

In this example, the dictionary person is unpacked into the function as name='Alice' and age=30. The function will output:

Hello, Alice. You are 30 years old.

**Using *args and **kwargs Together

Python allows you to accept an arbitrary number of positional and keyword arguments using *args and **kwargs, respectively. While *args collects positional arguments, **kwargs gathers keyword arguments into a dictionary.

Example:

def func(*args, **kwargs):
    print("Positional arguments:", args)
    print("Keyword arguments:", kwargs)

func(1, 2, 3, name="Alice", age=30)

Output:

Positional arguments: (1, 2, 3)
Keyword arguments: {'name': 'Alice', 'age': 30}

This way, *args stores the positional arguments (1, 2, 3) as a tuple, and **kwargs holds the keyword arguments {'name': 'Alice', 'age': 30} in a dictionary.

Learn More: Parameter Handling: *args and **kwargs in Python

**Merging Dictionaries Using ** in Python

Starting from Python 3.5, you can merge two or more dictionaries easily using the ** unpacking operator.

Example:

dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}

merged_dict = {**dict1, **dict2}
print(merged_dict)  # Output: {'a': 1, 'b': 2, 'c': 3, 'd': 4}

Here, **dict1 and **dict2 unpack the contents of both dictionaries into a new dictionary.

Learn More: Python Dictionaries: Key-Value Data Structures

**Handling Keyword-only Arguments

In Python, you can force certain arguments to be passed as keywords only, using **. This is useful when you want to ensure that arguments are explicitly named, rather than passed by position.

Example:

def my_function(*, name, age):
    print(f"Name: {name}, Age: {age}")

my_function(name="Alice", age=30)

If you try to call the function with positional arguments (like my_function("Alice", 30)), Python will throw an error. This enforces keyword-only arguments.

**Combining Lists and Dictionaries in Function Calls

You can pass both Python lists and dictionaries to a function by using *args and **kwargs together.

Example:

def display_info(*args, **kwargs):
    print("Positional:", args)
    print("Keyword:", kwargs)

data = [1, 2, 3]
info = {'name': 'Alice', 'age': 30}

display_info(*data, **info)

Output:

Positional: (1, 2, 3)
Keyword: {'name': 'Alice', 'age': 30}

In this case, *data unpacks the list into positional arguments, and **info unpacks the dictionary into keyword arguments.

Conclusion

The ** operator in Python is quite versatile. It handles everything from basic math operations like exponentiation to more advanced features like unpacking keyword arguments and merging dictionaries. As you practice, you’ll find that ** becomes a valuable tool for simplifying your Python code.

Share your love
Subhankar Rakshit
Subhankar Rakshit

Hey there! I’m Subhankar Rakshit, the brains behind PySeek. I’m a Post Graduate in Computer Science. PySeek is where I channel my love for Python programming and share it with the world through engaging and informative blogs.

Articles: 194