How to multiply arrays in Python

Learn to multiply arrays in Python with various methods. Explore tips, real-world applications, and how to debug common errors.

How to multiply arrays in Python
Published on: 
Tue
Mar 17, 2026
Updated on: 
Tue
Mar 24, 2026
The Replit Team

Array multiplication in Python is a common operation for data science. Whether you use the * operator or a library like NumPy, Python offers several ways to perform this task.

In this guide, you'll explore several techniques for array multiplication. You'll find practical tips, see real-world applications, and get advice to debug common errors for your own projects.

Using the * operator with NumPy arrays

import numpy as np
arr1 = np.array([1, 2, 3, 4])
arr2 = np.array([5, 6, 7, 8])
result = arr1 * arr2
print(result)--OUTPUT--[ 5 12 21 32]

When you use the * operator on two NumPy arrays of the same size, it performs element-wise multiplication. This means each element in the first array is multiplied by the element at the same position in the second array. This vectorized operation is a core reason NumPy is so efficient for numerical tasks.

In the example, the result is calculated by matching elements from arr1 and arr2:

  • The first elements (1 and 5) multiply to get 5.
  • The second elements (2 and 6) multiply to get 12.
  • This continues for all corresponding pairs in the arrays.

Basic multiplication techniques

Beyond the basic * operator, you can also perform element-wise multiplication with list comprehensions or leverage more advanced NumPy features like numpy.multiply() and broadcasting.

Element-wise multiplication with list comprehension

list1 = [1, 2, 3, 4]
list2 = [5, 6, 7, 8]
result = [a * b for a, b in zip(list1, list2)]
print(result)--OUTPUT--[5, 12, 21, 32]

For standard Python lists, a list comprehension offers a direct way to multiply elements. This technique relies on the zip() function to pair corresponding elements from each list.

  • The zip() function bundles elements from list1 and list2 into tuples like (1, 5), (2, 6), and so on.
  • The comprehension then iterates over these pairs, multiplying the two values (a * b) and collecting each result into a new list.

While more explicit than NumPy's operator, it's a powerful, built-in Python feature for when you aren't using external libraries.

Using the numpy.multiply() function

import numpy as np
arr1 = np.array([1, 2, 3, 4])
arr2 = np.array([5, 6, 7, 8])
result = np.multiply(arr1, arr2)
print(result)--OUTPUT--[ 5 12 21 32]

The numpy.multiply() function offers a more explicit way to perform element-wise multiplication. It's the functional equivalent of using the * operator on NumPy arrays and produces the exact same result.

  • This function is a NumPy universal function, or ufunc, which means it operates on arrays in an element-by-element fashion.

While the * operator is often more concise, using numpy.multiply() can improve code clarity—especially within complex mathematical formulas or when passing functions as arguments.

Broadcasting with NumPy arrays

import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
scalar = 10
result = arr * scalar
print(result)--OUTPUT--[[10 20 30]
[40 50 60]]

Broadcasting is a powerful NumPy feature that lets you perform arithmetic on arrays of different shapes. When you multiply an array like arr by a single number—a scalar—NumPy automatically handles the size mismatch. It does this by "broadcasting" the scalar across every element of the array.

  • In this case, the scalar 10 is multiplied with each element in arr, from 1 to 6.

This process allows you to apply an operation to an entire array without writing an explicit loop, making your code both cleaner and more efficient.

Advanced array multiplication

As your needs grow, you can tackle more complex tasks like matrix multiplication with the @ operator and optimize performance with advanced tools like einsum.

Matrix multiplication with the @ operator

import numpy as np
matrix1 = np.array([[1, 2], [3, 4]])
matrix2 = np.array([[5, 6], [7, 8]])
result = matrix1 @ matrix2 # equivalent to np.matmul(matrix1, matrix2)
print(result)--OUTPUT--[[19 22]
[43 50]]

The @ operator performs matrix multiplication, a different operation from the element-wise multiplication you get with *. It calculates the dot product by combining rows from the first matrix with columns from the second. This is essential for many linear algebra tasks.

  • In the example, the first element of the result, 19, is calculated from the first row of matrix1 and the first column of matrix2: (1*5) + (2*7).

This operator is a modern, readable shorthand for the numpy.matmul() function.

Using einsum for flexible array operations

import numpy as np
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
# Element-wise multiplication with Einstein notation
result = np.einsum('ij,ij->ij', arr1, arr2)
print(result)--OUTPUT--[[ 5 12]
[21 32]]

The numpy.einsum() function is a powerful tool that uses Einstein summation notation to perform complex array operations. The string expression, 'ij,ij->ij', is a concise recipe that dictates how the arrays are combined.

  • The input notation, ij,ij, tells the function that you're providing two 2D arrays, where i represents the row index and j represents the column index.
  • The output notation, ->ij, specifies that the resulting array should also be a 2D array with the same dimensions.

By matching the indices for the inputs and output, you're telling NumPy to perform element-wise multiplication. While this example is simple, einsum can handle much more, including matrix multiplication and transposing, just by changing the notation string.

Optimizing performance for large array multiplication

import numpy as np
import time

size = 1000
a = np.random.rand(size, size)
b = np.random.rand(size, size)

start = time.time()
c = a @ b
end = time.time()
print(f"Matrix multiplication of {size}x{size} arrays took {end-start:.4f} seconds")--OUTPUT--Matrix multiplication of 1000x1000 arrays took 0.1532 seconds

When working with large datasets, performance is key. This code measures how quickly NumPy handles matrix multiplication on two 1000x1000 arrays. NumPy is built for speed because its core functions are written in compiled languages like C, allowing it to execute complex math far faster than standard Python loops.

  • The time module captures the duration of the a @ b operation.
  • The output shows that multiplying these large arrays takes only a fraction of a second, which highlights NumPy's efficiency for numerical computing.

Move faster with Replit

Replit is an AI-powered development platform that transforms natural language into working applications. You can describe what you want to build, and Replit Agent creates it—complete with databases, APIs, and deployment.

For the array multiplication techniques we've explored, Replit Agent can turn them into production-ready applications:

  • Build an image editor that adjusts brightness by multiplying pixel data with a scalar, using the broadcasting technique.
  • Create a financial modeling tool that uses matrix multiplication with the @ operator to calculate investment portfolio returns.
  • Deploy a data analysis utility that applies weights to a dataset using element-wise multiplication.

Turn your own concepts into working software. Describe your app idea and let Replit Agent write the code, test it, and handle deployment automatically.

Common errors and challenges

When multiplying arrays in Python, you might run into a few common issues, from shape mismatches to using the wrong operator.

Fixing shape mismatch in array multiplication

A ValueError due to shape mismatch is a frequent hurdle. This happens when the dimensions of your arrays aren't compatible for the operation you're attempting. For element-wise multiplication with the * operator, arrays must have the same shape (unless broadcasting applies). For matrix multiplication with the @ operator, the inner dimensions must match—for example, a (3, 4) matrix can multiply a (4, 2) matrix, but not another (3, 4) matrix.

Always check each array's dimensions using the .shape attribute before performing an operation. If they don't align, you may need to reshape one of the arrays to ensure compatibility.

Understanding the difference between * and @ operators

Confusing the * and @ operators is another common pitfall. While both perform multiplication, they serve entirely different mathematical purposes, and using the wrong one can lead to shape errors or silently incorrect results.

  • Use the * operator for element-wise multiplication, like scaling every value in a dataset by a certain factor.
  • Use the @ operator for matrix multiplication, which is essential for linear algebra tasks like geometric transformations or solving systems of equations.

Handling division by zero in array operations

Although not strictly a multiplication error, division by zero often appears in related workflows, such as when normalizing data. NumPy handles this gracefully by not crashing your program. Instead, it will return inf (infinity) or nan (not a number) in the resulting array.

You can manage these values by checking for zeros before the division or by using a function like numpy.nan_to_num() to replace them with a valid number afterward.

Fixing shape mismatch in array multiplication

The ValueError for shape mismatch is an error you'll definitely encounter. It's NumPy's way of telling you that the arrays in your operation don't have compatible dimensions. The following code demonstrates a common scenario where this happens with element-wise multiplication.

import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([[1, 2], [3, 4], [5, 6]])
# This raises ValueError: operands could not be broadcast together
result = arr1 * arr2

Here, the multiplication fails because NumPy can't stretch the 1D arr1 to match the 2D shape of arr2. Their dimensions don't line up for an element-wise operation. The following code adjusts one array to resolve this.

import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([[1, 2], [3, 4], [5, 6]])
# Reshape arr1 to column vector for proper broadcasting
arr1 = arr1.reshape(-1, 1)
result = arr1 * arr2
print(result)

The fix works by using reshape(-1, 1) to transform the 1D arr1 into a 2D column vector. This adjustment aligns the array dimensions, which allows NumPy’s broadcasting rules to apply correctly.

  • The reshaped array’s single column is effectively “stretched” across the columns of arr2.
  • This enables element-wise multiplication to proceed row by row without a shape conflict.

You’ll often need this fix when combining 1D and 2D arrays in an operation.

Understanding the difference between * and @ operators

It’s easy to mix up the * and @ operators, but doing so can lead to silent errors. Instead of crashing, your code will run and produce an incorrect result. The following example demonstrates what happens when you accidentally use * for matrix multiplication.

import numpy as np
matrix1 = np.array([[1, 2], [3, 4]])
matrix2 = np.array([[5, 6], [7, 8]])
# This performs element-wise multiplication, not matrix multiplication
result = matrix1 * matrix2
print(result)

The code uses the * operator, which multiplies corresponding elements from each matrix. This gives you an element-wise result instead of the correct dot product. The next example shows how to perform true matrix multiplication.

import numpy as np
matrix1 = np.array([[1, 2], [3, 4]])
matrix2 = np.array([[5, 6], [7, 8]])
# Use @ operator for matrix multiplication
result = matrix1 @ matrix2
print(result)

The fix is to use the @ operator, which performs true matrix multiplication by calculating the dot product. This is different from the element-wise multiplication you get with the * operator. You'll need to be mindful of this distinction for any linear algebra task.

  • Using * instead of @ won't raise an error for matrices of the same size.
  • It will just produce a mathematically incorrect result, making it a tricky bug to spot.

Handling division by zero in array operations

When you divide by an array containing a zero, NumPy won't halt your script. It will instead produce a RuntimeWarning and insert special values like inf into the output. The following code shows exactly what happens in this scenario.

import numpy as np
arr1 = np.array([1, 2, 0, 4])
arr2 = np.array([5, 6, 7, 8])
# This produces runtime warning and Inf values
result = arr2 / arr1
print(result)

The code divides arr2 by arr1, but the third element in arr1 is 0, causing the operation to fail at that position. The next example shows how you can clean up the resulting array.

import numpy as np
arr1 = np.array([1, 2, 0, 4])
arr2 = np.array([5, 6, 7, 8])
# Use np.divide with where parameter to handle zeros
result = np.divide(arr2, arr1, out=np.zeros_like(arr2), where=arr1!=0)
print(result)

The fix uses numpy.divide() to prevent division-by-zero errors. This function gives you more control than the standard / operator.

  • The where parameter takes a condition—in this case, arr1!=0—and only performs the division where it’s true.
  • The out parameter provides a default value for positions where the condition is false, preventing inf values from appearing in your result.

This is a clean way to handle potential errors when normalizing data.

Real-world applications

Now that you can multiply arrays and navigate common errors, you can apply these skills to real-world problems in finance and machine learning.

Stock portfolio value calculation with * operator

Broadcasting with the * operator provides a simple method for calculating the daily value of a stock portfolio by multiplying an array of prices by a single number representing your shares.

import numpy as np

# Stock prices for 5 consecutive days
stock_prices = np.array([150.25, 152.50, 151.75, 153.00, 155.75])

# Number of shares owned
shares = 10

# Calculate daily portfolio value
portfolio_values = stock_prices * shares

print("Stock prices ($):", stock_prices)
print("Shares owned:", shares)
print("Daily portfolio values ($):", portfolio_values)

This code calculates the daily value of a stock portfolio by multiplying an array of prices by a single number. The operation between the stock_prices array and the scalar shares is automatically applied to every price in the array at once.

  • The * operator takes the shares value and multiplies it against each daily price in the stock_prices array.
  • The result, portfolio_values, is a new array containing the total portfolio value for each day.

This vectorized approach avoids an explicit loop, making the code more concise and performant. This is a key advantage of using NumPy for numerical tasks.

Feature scaling in machine learning with NumPy array operations

In machine learning, feature scaling is a crucial preprocessing step that brings all your data into a consistent range, and NumPy's array operations make this task straightforward.

import numpy as np

# Sample dataset with 3 features
data = np.array([[45, 85, 32], [23, 51, 19], [67, 92, 65], [10, 39, 24]])

# Min-max scaling: (x - min) / (max - min)
min_vals = np.min(data, axis=0)
max_vals = np.max(data, axis=0)
scaled_data = (data - min_vals) / (max_vals - min_vals)

print("Original data:\n", data)
print("\nNormalized data (0-1 scale):\n", scaled_data)

This code performs min-max scaling to normalize a dataset, rescaling each feature to a common 0-to-1 range. This is a standard preprocessing step that prevents features with larger values from unfairly dominating a machine learning model's calculations.

  • The functions np.min() and np.max() are used with axis=0 to find the minimum and maximum values down each column, or feature.
  • The final line applies the scaling formula. NumPy's broadcasting automatically subtracts the minimums and divides by the range for the entire dataset, all without needing a loop.

Get started with Replit

Turn these concepts into a real tool. Describe what you want to build, like “a web app that uses NumPy broadcasting to adjust image brightness” or “a dashboard that uses the @ operator to calculate portfolio returns.”

Replit Agent will write the code, test for errors, and deploy your app automatically. Start building with Replit.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

Get started for free

Create & deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.