New to Rust? Grab our free Rust for Beginners eBook Get it free →
np.arange in Python: syntax, parameters and examples

np.arange() is the NumPy function you reach for whenever you need a sequence of numbers instead of a full list from Python’s range(). It builds an array directly, so slicing, reshaping and vectorized math all work on the result right away. This guide covers every parameter, how dtype gets picked, the edge cases that trip people up and where np.arange() falls short compared to np.linspace().
Syntax and parameters of np.arange
np.arange() takes up to four positional arguments and only stop is required.
numpy.arange(start, stop, step, dtype=None)
- start: the first value of the sequence. Optional, defaults to 0.
- stop: the value the sequence ends before. Required. The output never includes this value.
- step: the gap between consecutive values. Optional, defaults to 1. If you pass step as a positional argument, you also need to pass start.
- dtype: the data type of the returned array. Optional. NumPy infers it from start, stop and step when you leave it out.
Recent NumPy releases (2.0 and later) also accept two keyword-only arguments, device and like, mainly useful for array-API interoperability rather than everyday scripts. Older references built against pre-2.0 releases won’t mention either one, so if you’re following an older tutorial and see an error about an unexpected keyword, that’s usually why.
Basic examples of np.arange()
The five examples below cover every combination of arguments you’ll use day to day, from a single stop value up to a full start, stop, step and dtype call.
Example 1: by specifying only stop
np.arange(10) only sets stop, so NumPy assumes start is 0 and step is 1 without you writing either one.
import numpy as np
np.arange(10)
That single number is enough to build a full sequence, since NumPy already knows where to start and how far to step between values.
Output:

The result counts from 0 up to 9, stopping one short of 10 because stop marks the boundary and never appears in the output itself. This single-argument form is the one you’ll type most often, since it matches the shape of a plain Python for loop counter while still returning a NumPy array you can reshape or run math on.
Example 2: by specifying start and stop
Adding a second argument changes what NumPy reads as start, since two positional values are always start followed by stop.
np.arange(1,10)
start now pins the first value at 1 instead of the default 0, while stop still marks where counting ends without being included.
Output:

Step stays at its default of 1 here, so the array counts up one at a time from 1 through 9. There’s no way to pass stop alone without also naming it as a keyword, since two bare positional arguments are always read as start then stop.
Example 3: by specifying start, stop and step
A third positional argument controls the spacing between values instead of just the boundaries of the range.
np.arange(1,10,2)
step of 2 means NumPy skips every other integer between start and stop rather than counting one by one.
Output:

The result lands on 1, 3, 5, 7 and 9, since each value adds 2 to the last one until it would reach or pass 10. Changing step from a positive to a negative number flips this into a countdown instead, which the next section covers directly.
Example 4: by specifying the stop and dtype
dtype becomes relevant once you need the array’s values in a type other than what NumPy would infer on its own.
np.arange(20,dtype="complex")
Passing dtype=”complex” tells NumPy to store every value as a complex number even though stop is a plain integer.
Output:

The array still counts from 0 to 19, but each value now carries a complex representation, useful when the numbers feed into a calculation that expects that type downstream. Forcing a dtype like this is also how you catch a mismatch early, since an incompatible dtype raises an error right where the array gets built rather than later in your code.
Example 5: by specifying the start, stop, step and dtype
Combining every argument at once shows how they interact together rather than one at a time.
np.arange(1,10,2,dtype="float")
start of 1, stop of 10, step of 2 and dtype as float together produce the same spacing as example 3, just cast to floating-point values instead of integers.
Output:

In the above output, we got an array with values from 1 to 9 and the difference between the values is 2. Also, the datatype of those values is float. This is the full signature in one call and it’s worth reaching for whenever a script downstream expects a fixed numeric type rather than whatever NumPy would infer on its own.
Negative arguments and counting backwards
np.arange() works the same way with negative numbers as long as step stays positive. A negative start with a positive step still counts upward toward stop.
import numpy as np
np.arange(-5, -1)
Output: array([-5, -4, -3, -2])
To count backwards, pair a negative step with a start value greater than stop.
np.arange(5, 1, -1)
Output: array([5, 4, 3, 2])
The array begins at start and moves toward stop by step each time, stopping just before stop is reached. This pattern is a direct way to build a countdown sequence or generate reversed indices without slicing a separate array afterward.
Getting empty arrays
Some argument combinations return an empty array instead of raising an error and it helps to recognize them ahead of time.
import numpy as np
np.arange(2, 2)
Output: array([], dtype=int64)
Equal start and stop values always produce an empty array, since the range excludes stop and nothing is left between the two. The same happens when start is greater than stop with a positive step, or when start is less than stop with a negative step. NumPy treats none of these as errors. If a script expects a populated array and gets an empty one, check the sign of step against the direction of start and stop before assuming something else broke further up the code.
Floating-point steps and precision
Integer arguments behave predictably, but a floating-point step can introduce small rounding differences. NumPy calculates the array length as ceil((stop – start) / step) and floating-point round-off can occasionally push the last value slightly past stop or drop it just short.
import numpy as np
np.arange(0, 1, 0.2)
Output: array([0., 0.2, 0.4, 0.6, 0.8])
Casting the result to an integer dtype makes this worse, since NumPy computes the step in the target dtype rather than the dtype you originally passed in. np.arange(0, 5, 0.5, dtype=int) does not give five evenly spaced integers, it repeats a truncated value because the 0.5 step collapses under integer casting. Whenever a non-integer step matters for the exact count of values, reach for np.linspace() instead, since it takes the number of points directly rather than deriving it from a step size.
np.arange compared with Python’s range function
np.arange() and Python’s built-in range() share the same three parameters, start, stop and step, but they solve different problems. range() returns a range object built for iteration in a for loop, storing only the three numbers and calculating each value on demand. That keeps memory use flat no matter how long the sequence gets.
np.arange() returns a full NumPy array with every value computed and stored right away. That makes it the better choice for vectorized math, reshaping or handing the values to a library like Matplotlib or pandas. It also accepts floating-point arguments and lets you set the dtype directly, neither of which range() supports.
For a plain counting loop that never touches NumPy, range() stays faster and lighter. Reach for np.arange() once the numbers themselves need to become part of an array.
np.arange compared with np.linspace
np.arange() and np.linspace() both build evenly spaced sequences and the choice between them comes down to what you know ahead of time. With np.arange(), you fix the step size and let NumPy work out how many values fit between start and stop. With np.linspace(), you fix the total number of values instead and let NumPy calculate the spacing between them.
import numpy as np
np.linspace(0, 1, 5)
Output: array([0., 0.25, 0.5, 0.75, 1.])
Notice that np.linspace() includes the stop value by default, unlike np.arange() which excludes it. This matters most with floating-point ranges, where np.arange() can produce an inconsistent element count due to rounding, while np.linspace() always returns exactly the count you asked for.
Combining np.arange with other NumPy functions
np.arange() rarely stays a flat 1D array in real code. It’s common to reshape the result into a matrix, or feed it into a function that works element-wise.
import numpy as np
grid = np.arange(6).reshape((2, 3))
print(grid)
Output: array([[0, 1, 2], [3, 4, 5]])
The reshape function turns the flat sequence into any shape whose total element count matches, which is a common first step before matrix operations.
np.arange() also plays well with universal functions. Squaring, computing a sine wave or building an outer product all work directly on the array without a manual loop.
x = np.arange(5)
np.sin(x)
If you need every pairwise product between two sequences built with arange, the outer product function takes both arrays directly and skips the nested loop entirely.
Filtering values from an arange sequence
Boolean indexing pulls chosen values out of a sequence built with np.arange() without writing a separate loop.
import numpy as np
sequence = np.arange(0, 20, 3)
filtered = sequence[sequence > 10]
print(filtered)
Output: array([12, 15, 18])
sequence > 10 builds a boolean array the same length as sequence and indexing with it keeps only the positions where the condition is true. This pattern shows up often when cleaning generated data, picking values above or below a threshold, or building a mask for a plotting function. It replaces a manual for loop with a single line and it works with comparison operators including equality checks and combined conditions using the bitwise and and or operators.
Practical use cases for np.arange
np.arange() shows up anywhere a script needs a predictable numeric sequence rather than random or manually typed values.
Plotting is the most common case. A function like Matplotlib expects an array of x values to pair with computed y values.
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 10, 0.1)
y = np.sin(x)
plt.plot(x, y)
This generates a smooth curve because the step of 0.1 packs enough points into the range. The guide on 3D plotting with Matplotlib extends this same pattern into three dimensions.
Time-based sequences are another frequent use case, generating hourly timestamps for a day or monthly indices for a year of data. np.arange() also underlies numeric derivative calculations, where evenly spaced sample points feed into a function like np.gradient to estimate rates of change from data. Anywhere you would reach for a loop counter that also needs to behave like a NumPy array, np.arange() is the direct replacement.
Key takeaways
- np.arange() builds a NumPy array, unlike Python’s range() which returns an iterator
- stop is the only required argument and the output always excludes it
- step must be nonzero or NumPy raises a ZeroDivisionError
- negative step values count backward from a larger start to a smaller stop
- floating-point steps can shift the array length due to rounding
- reach for np.linspace() when you need an exact number of points instead of a fixed step
- boolean indexing filters an arange array without writing a loop
- reshape turns the flat output into any compatible multi-dimensional shape
Frequently asked questions
What does np.arange() return?
np.arange() returns a one-dimensional NumPy ndarray containing evenly spaced values between start and stop, spaced apart by step, with stop excluded from the result.
Why does np.arange(5) start at zero?
A single positional argument to np.arange() is always treated as stop. Start defaults to 0 and step defaults to 1 when you omit them, so np.arange(5) gives 0 through 4.
Can np.arange() accept negative numbers?
Yes. Negative start and stop values work normally with a positive step. Pairing a negative step with a start greater than stop produces a descending sequence instead.
What is the difference between np.arange() and np.linspace()?
np.arange() takes a step size and calculates how many values fit, while np.linspace() takes a count of points and calculates the spacing, including the endpoint by default.
Why do I get a ZeroDivisionError from np.arange()?
Passing step=0 raises this error, since NumPy cannot determine how many increments separate start from stop without a nonzero step value.
Does np.arange() include the stop value?
No. The interval is half open, so the sequence stops just before reaching stop, matching how Python’s built-in range() function behaves.
Can np.arange() generate multi-dimensional arrays directly?
No, np.arange() always returns a flat one-dimensional array. Reshape the output afterward with reshape() to arrange the same values into two or more dimensions.
Conclusion
np.arange() covers most sequence-generation needs once you know how stop, step and dtype interact and how it differs from range() and linspace() for the cases each one handles better. Start with the basic parameter combinations, then bring in reshaping, filtering and plotting as a script grows more involved.




