# Python ** Explained (Double Star or Double Asterix)

In Python programming, you may encounter various operators that perform specific operations. One such operator is the double star operator (**). Understanding its function and usage is essential to make the most of your Python programming experience.

The double star operator, denoted by (**), is an arithmetic operator in Python often used for exponentiation. In other words, it’s a power operator that raises the number on its left to the power of the number on its right. It also plays a role in function calls to unpack keyword arguments. By prefixing a dictionary with the ** operator, you can provide keyword arguments to a function based on the dictionary’s key-value pairs.

Recognizing this operator’s purpose will allow you to manipulate and calculate numbers more efficiently in your code. You can also use it to create cleaner and more dynamic code when working with Python dictionaries.

Let’s dive into the various ways you can use the ** operator.

## How to Use the Double Star Operator (**) in Python

In Python, the double asterisks have many uses. They find applications in arithmetic operations, function arguments, and dictionary data structures.

Let’s look at these applications:

### 1. Exponentiation Operations with **

In Python arithmetic, the double asterisks represent exponentiation, which is a type of arithmetic operation. It allows you to raise a number to the power of another number.

This means that, given two numbers a and b, the expression ‘a**b’ calculates the value of a raised to the power of b. The double star operator is part of Python’s arithmetic operators, which also include addition (+), subtraction (-), multiplication (*), division (/), integer division (//), and modulo (%).

Here’s an example of using the double star operator for exponentiation:

``````a = 3
b = 2
result = a ** b
print(result)``````

Output:

``9``

In this example, a is raised to the power of b, resulting in the value of 9 (3 ** 2). You can also use the double star operator with various numeric data types, such as integers, floats, and complex numbers.

Here’s an example with different data types:

``````a = 10
b = 2
result1 = a ** b

a = 1.5
b = 2.5
result2 = a ** b

a = 3 + 2j
b = 3 + 5j
result3 = a ** b

print(result1)
print(result2)
print(result3)``````

Output:

``````100
2.7556759606310752
(-0.7851059645317211+2.350232331971346j)``````

You can also use the pow() function to perform exponentiation:

``````z = pow(2, 3)
print(z) ``````

Output:

``8``

The pow() function takes two arguments: the first argument is the base, and the second argument is the exponent. The function returns the result of raising the base to the power of the exponent, as shown in the example above.

You can read more about the pow() function in this article on How to Square in Python!

#### Double Asterisk ** Operator Precedence

It’s important to understand the precedence of arithmetic operators in Python when using the double star operator with other arithmetic operators. The order of precedence, from highest to lowest, is as follows:

1. Exponentiation (**)
2. Negation ()
3. Multiplication, Division, Integer Division, and Modulo (*, /, //, %)
4. Addition and Subtraction (+, )

This means that exponentiation operations will be executed before any other arithmetic operations in an expression.

``````x = 2 + 3 ** 2
print(x)  ``````

Output:

``11``

In the above example, the exponentiation operation (3 ** 2) is executed first, resulting in a value of 9. Then, the addition operation (2 + 9) is executed, giving a final result of 11 for x.

When performing complex calculations, it’s better to break down expressions using parentheses. This ensures that Python carries out all operations in the correct order.

We can rewrite the previous example as:

``````y = (2 + 3) ** 2
print(y)  ``````

Output:

``25``

In this case, the addition operation (2 + 3) is executed first due to the parentheses, resulting in a value of 5. Then, the exponentiation operation (5 ** 2) is executed, giving a final result of 25 for y.

### 2. Using ** for Keyword Arguments in Function Definitions

Double asterisks serve another purpose in function definitions and calls. In function definitions, the double asterisk (**) is used before a parameter to collect keyword arguments into a Python dictionary.

Similarly, in function calls, the double asterisk (**) can be used to unpack a dictionary and pass its key-value pairs as keyword arguments to the function. Here is an example:

``````def example_function(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")

parameters = {'param1': 'value1', 'param2': 'value2'}
example_function(**parameters)``````

Output:

``````param1: value1
param2: value2``````

In the above code, the example_function accepts keyword arguments, which are collected inside the kwargs dictionary. When the function is called with the **parameters syntax, the dictionary is unpacked, and its key-value pairs are passed as keyword arguments.

To properly understand the role of the double asterisk operator in a function definition, let’s shed a bit more light on the type of arguments in a function definition:

#### i. Positional Arguments

In Python, positional arguments are inputs passed to a function in the order in which they are defined in the function definition. For example, consider the following function:

``````def greet(name, greeting):
print(f"{greeting}, {name}!")``````

Here, name and greeting are positional arguments. When you call the function, you provide these arguments in the same order as they appear in the function definition:

``greet("John", "Hello")``

Output:

``Hello, John!``

#### ii. Keyword Arguments

Keyword arguments, also known as named arguments, are function inputs that are identified by the keyword or parameter name they are assigned to. A keyword argument can be passed to a function in any order as long as its parameter name is specified.

Using the same greet function as before, you can call it with keyword arguments like this:

``greet(name="John", greeting="Hello")``

Python also supports default values for parameters, making them optional when calling the function:

``````def greet(name, greeting="Hello"):
print(f"{greeting}, {name}!")

greet("John")    ``````

Output:

``Hello, John!``

In the example above, we use just one positional argument since we already have a default value for the second positional argument.

#### iii. *Args and **Kwargs

In Python, you may come across functions that need to accept a variable number of arguments. To handle variable arguments, the special notation *args and **kwargs can be used in the function signature.

*args represents a variable-length list of positional arguments. It allows you to pass any number of positional arguments to the function, which are then collected into a tuple.

For example:

``````def add_numbers(*args):
total = 0
for num in args:
total += num
``````

You can call the add_numbers function with any number of arguments:

``````add_numbers(1, 2, 3)
add_numbers(10, 33, 4, 6 ,7, 7, 28)``````

Output:

``````6
95``````

As we can see, there is no limit to how many arguments we can pass into the function. The function can accept unlimited positional arguments.

**kwargs, on the other hand, is used to collect a variable-length argument dictionary of keyword arguments. It allows you to pass any number of keyword arguments to the function, which are then collected into a dictionary.

For example:

``````def print_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
``````

You can call the print_info function with any number of keyword arguments:

``print_info(name="John", age=30, city="New York")``

Output:

``````name: John
age: 30
city: New York``````

In summary, Python functions use positional and keyword arguments when accepting inputs. The special notations args and *kwargs provide flexibility for handling variable-length lists of arguments in function calls. By properly using these features, you can create clean and efficient code that is easy to read and understand.

Keep in mind that the double star operator’s behavior is different depending on its usage, either as an exponentiation operator or as a means to handle keyword arguments in functions.

### 3. Unpacking Dictionaries with **

In Python, you’ll often come across the double star operator (**) whilst working with dictionaries. You can use the double-star operator to unpack a dictionary.

After unpacking the dictionary, you can pass its key-value pairs as positional arguments to a function. This can be particularly useful when you have a dictionary containing relevant function arguments.

Here’s an example:

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

person = {'name': 'Alice', 'age': 30}

result = greet(**person)  # equivalent to greet(name='Alice', age=30)
print(result)  # Output: "Hello, Alice! You are 30 years old."
``````

In the code above, the **person syntax unpacks the person dictionary, passing its values as arguments to the greet function call. This makes it easier to work with dictionaries when calling functions.

You can check out this data structure in our article on How To Build A Google News Aggregator In Power BI Using Python.

### 4. Merging Dictionaries

Another handy feature of the double star operator is merging dictionaries. If you have two dictionaries and want to create a new one that contains the items of both, you can use the double star operator in conjunction with dictionary literals. Here’s how:

``````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}``

In the example above, {**dict1, **dict2} unpacks both dictionaries and combines their key-value pairs into a new dictionary. Note that if the dictionaries share keys, the values in the second dictionary will take precedence and overwrite those in the first.

Keep these uses of the double star operator in mind when working with dictionaries in Python, and leverage it to streamline your code and enhance its readability.

## Memory and Performance Considerations with the ** Operator

The double-star operator (**) operator possesses certain memory and performance attributes that you should be aware of when incorporating it into your code.

When comparing the double-star operator to the built-in pow() function, the former is generally faster and more commonly used. The double-star operator (**), being an arithmetic operator, requires less memory compared to a function like pow().

This is primarily due to the fact that pow() requires additional memory locations for its input parameters.

Consider a scenario where you are working with large data sets or performing numerous calculations. In such a case, the optimal choice for memory and performance would likely be the double-star operator.

The increased efficiency may lead to a more streamlined execution process, potentially reducing the computational burden on your system.

It is crucial, however, to remember that the performance difference between the two choices might not be significant for smaller data sets or basic calculations. Therefore, it is advisable to select the most appropriate approach based on your specific use case.

To summarize, the double-star operator in Python offers some benefits. These benefits include reduced memory consumption and faster execution times, compared to using the pow() function.

## Python Version Differences

In Python, the double-star operator (**) is used for exponentiation, where one number is raised to the power of another. This operator is available and functions the same way in both Python 2 and Python 3.

For example, if you want to calculate 2 raised to the power of 3, you would use 2 ** 3, which would return 8. No matter whether you are working in Python 2 or Python 3, this operation would yield the same result.

For instance, consider the following function definition:

``````def example_function(a, b, **kwargs):
print(a)
print(b)
print(kwargs)
``````

In this case, a and b are positional arguments, and kwargs is a dictionary that stores any additional keyword arguments passed to the function.

Furthermore, this pattern is consistent in both Python 2 and Python 3, so you can use it in your code with confidence, regardless of the version you are working with.

In summary, the double-star operator serves two main purposes in Python:

1. Exponentiation in mathematical calculations
2. Allowing functions to accept varying numbers of keyword arguments

These functionalities remain consistent across Python 2 and Python 3, so you can use the double-star operator with confidence, knowing that it functions similarly in both versions of the language.

## Final Thoughts

In this tutorial, you have learned about the double-star operator (**) in the Python programming language. By understanding the nuances of the double-star operator, you are better equipped to create clear and efficient code, improving the overall quality of your Python programming.

Remember, the double-star operator is an arithmetic operator used for exponentiation. Additionally, it is used in function definitions to accept a variable number of keyword arguments. When employed in this manner, it provides a concise and clean way of handling keyword arguments in a function, making you a more effective Python developer.

With this newly acquired knowledge, you can be more confident and knowledgeable in your coding endeavors, making your code more robust and efficient. Keep honing your skills, and always remain open to learning new techniques and approaches, as the world of Python programming is vast and constantly evolving!

If this article captures your interest, we encourage you to peruse our article on How to Check if A Dictionary is Empty.

## Frequently Asked Questions

### What happens if there is a conflict while merging dictionaries with **?

A conflict occurs when one or more keys are present in both of the dictionaries to be merged. In this case, the key in the second dictionary wins out and overwrites the first one in the new, merged dictionary.

For example:

``````a = {'name': 'John', 'age': 32, 'country': 'Denmark'}
b = {'country': 'United Kingdom', 'city': 'London', 'team':'chelsea'}

c = {**a, **b}
print(c)``````

Output:

``{'name': 'John', 'age': 32, 'country': 'United Kingdom', 'city': 'London', 'team': 'chelsea'}``

Both dictionaries contain the key country. In the final merged dictionary, the value for the key corresponds to the value in the second dictionary b.

### Are the args, kwargs keywords necessary?

No, they are not necessary. The only syntax compulsory is the single (*) and double asterisks(**). For example, look at these function definitions:

``````def test_func1(*boo):
pass

def test_func2(**foo):
pass``````

In the functions above, boo will still collect positional arguments and store them in a tuple, while foo will collect keyword-only arguments and store them in a dictionary.

However, it is better to stick to the standard args and kwargs convention to avoid confusion.

### Can you use *args and**kwargs together in the same function definition?

Yes, you can use both of them in the same function definition. Here’s an example:

``````def print_func(*args, **kwargs):
print(args)
print(kwargs)

print_func('tea', 'toast', 'bacon', 'eggs', meal = 'breakfast', time='morning')``````

Output:

``````('tea', 'toast', 'bacon', 'eggs')
{'meal': 'breakfast', 'time': 'morning'}``````

We can see that the function captures the non-keyword arguments in a tuple and places the keyword arguments in a dictionary. You can specify positional arguments in the function definition. However, always make sure they are ahead of the *args argument.

Also, ensure that all positional arguments, including *args are always ahead of keyword arguments. For example:

``````def print_func(meal,*args, **kwargs):
print(meal)
print(args)
print(kwargs)

print_func('breakfast', 'tea', 'toast', time ='morning', 'bacon', 'eggs')``````

Output:

``````  Cell In[1], line 6
print_func('breakfast', 'tea', 'toast', time='morning', 'bacon', 'eggs')
^
SyntaxError: positional argument follows keyword argument``````

The error occurs because we have the positional arguments bacon and eggs following a keyword argument.

## Merging, Grouping, and Pivoting with Python Pandas

Master the advanced capabilities of Pandas for complex data manipulation tasks in Python through merging, grouping, and pivoting techniques.

## Introduction to Data Preprocessing with Scikit-learn

A concise guide to mastering the fundamentals of data preprocessing using Scikit-learn. This course is designed for beginners to gain practical skills and theoretical knowledge.

## Building Dashboards with Plotly Dash

Master the art of creating interactive, data-driven dashboards using Plotly Dash.

## Advanced Data Manipulation with Pandas – Merging, Grouping, and Pivoting

Master the advanced capabilities of Pandas for complex data manipulation tasks in Python through merging, grouping, and pivoting techniques.

## Mastering Exploratory Data Analysis (EDA) with Python

A comprehensive guide to effectively performing Exploratory Data Analysis (EDA) using Python, focusing on best practices and powerful tools.

## Visualizing Data with Matplotlib: A Beginner’s Guide

A comprehensive guide designed to introduce beginners to the powerful data visualization capabilities of Matplotlib.

## Using Python for Time Series Analysis: An Introduction

Learn the fundamentals of time series analysis using Python, from data preparation to advanced forecasting techniques.

## Mastering Data Analysis in Jupyter Notebooks: Tips and Tricks

Comprehensive guidance on using Jupyter Notebooks for effective and efficient data analysis.

## Crafting Unique Data Visualizations with Matplotlib in Python

A comprehensive guide to creating custom data visualizations using Matplotlib in Python.

## Kickstart Your Data Analysis Journey with Python: Setting Up Your Environment

Data analysis has become an essential skill in many industries. Professionals who can derive meaningful...

## HR Data Analysis in Python Using Google Colab

A hands-on project for analyzing HR datasets using Python in Google Colab. From data importation to advanced analytics, this project will cover all essential aspects.

## Building a Beginner Streamlit Application for Data Tasks

This project will guide you through the process of creating a basic Streamlit application to perform data-related tasks.