Ranges and Slices in Julia and Python

Using ranges to get or set parts of an array

Ranges can look quite similar in both Python and Julia, however the apparent similarity can be deceptive as they work entirely different.

Here is an example of creating an array and accessing a subset of it in Julia. Notice that Julia has 1-based indices, meaning first element is at index 1.

The example in Python looks very similar:

Julia Ranges

But here is where it starts getting different. In Julia is an operator just like or . Operators in Julia are just syntax sugar for function calls. So in Julia is just syntax sugar for , to avoid ambiguity one writes . Thus in Julia is the same as writing .

This has implications for how we use it. In Julia I can put a range into an object using the colon syntax:

If we check the step, you can see that does not exist for a .

However we can explicitly specify a step with the colon syntax.

This allows us to extract every other elements from the array :

What helps understand how Julia actually operates is that so much of Julia’s functionality is written in Julia itself. To open a preconfigured editor at the file and line containing the code for the function called you can use the macro. So e.g. if I want to know how range access in arrays are implemented I can write:

This opens up the file at line 736, showing me this code:

If instead I try to use a single integer index:

I will get this code:

This is not that readable if you don’t have some deeper understanding of Julia. I could write a wrong but simplified version of this for easier understanding:

is a builtin function implemented in C and not Julia code. This means that the index operator is not really implemented at C level. Every place is used, Julia will call . As you've seen in the examples is overloaded, so there will be different implementations called depending on what sort of index you are using.

Python Ranges and Slices

Okay enough about Julia. Let us study the situation in Python land more. In Python is not an operator producing range objects. This example proves that:

Instead you must use the function. Its behavior is different between Python 2.x and Python 3.x. In 2.x it will create an array:

Python has both arrays and lists, for the cases where Julia would simple use arrays. Most of the time when talking about arrays, I am implying lists in python, since they serve as similar usage to arrays in Julia.

However in Python 3.x we instead get a range object, which is more similar to Julia:

Which you can see have similar properties. However Python does not differentiate between and .

However if we try to use a range, we quickly discover that does not work:

Python distinguishes between ranges and slices. You can use a range in say a for-loop, however to access a range of array elements you need to use a slice object.

You can see that the properties of a slice can be inspected much the same way as a range in either Julia or Python:

Another example of their differences is when creating lists.

You can see that ranges can be used but not slices. In Julia this would not make a difference. You could write:

Or even use the for exploding arrays into arguments.

Observations and Reflections

Relearning Python after having used Julia for many years, I this as just another case, where I think Python lacks coherency and clarity.

I think Julia presents a more elegant design which is more flexible. By letting the construct range objects, you can merge several usage patterns into one.

The difficulty of accomplishing this in Python is most likely due to the fact that Python does not allow function overloading in the same way. Python is a single dispatch language, which means only one object can be used to pick the right function to execute at run time.

Julia in contrast supports multiple dispatch, meaning every argument to a function determines which particular implementation gets picked at runtime. This makes it possible to define range and index access for different types of objects easily.

Ironically the high performance of Julia makes it a more user-friendly language. Due to the high performance of Julia code, much more of the Julia functionality is implemented in Julia itself and don’t represent special cases as with Python. Thus using the macro is a very effective way of inspecting how almost anything works in Julia. In Python I don't have access to any similar functionality, which makes me quickly check how some particular functionality works in Python.

Geek dad, living in Oslo, Norway with passion for UX, Julia programming, science, teaching, reading and writing.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store