range function
The known Python range function, which they taught us in our programming beginnings to use in a for loop, it is possible that in many cases we can replace it with better options and with cleaner and more modern code. This function has its origin in the C/C++/Java languages, predecessors of this programming language, and they really need an index loop variable, but in this programming language it is not necessary to have this index.
The loop for an iterable sequence usually looks like this:
for x in range(len(seq)):
#haz_something_with (seq[x])
The variable x is used only to access the next element from the iterable. Since Python “for"is a loop"foreach”, I believe, that there is a better way to do this; iterating directly over the iterable (hence the name) and it would look like this:
for thing in sequence:
#HDo_something_with (thing)
Which in a simple case would look like this:

and would give the expected result for each value in the iteration and using the value defined in the sequence:
>>27
>>64
This way of direct iteration It's about 30% faster, doesn't require creating the indexes, and is easier to read the code (“for [each] element in [that] sequence, do something with [that element].
Enumerate function
To modify each element in a mutable iterable, we also have no problem for not having an index. In that case we have another function available: “enumerate yourself”, which returns a generator that produces tuples of elements and their respective indices in the form (x,seq[x]).
Let's look at the code of a very simple case:
for x, thing in enumerate(seq):
seq[x] = do_something_with(item)
We are going to do it with a simple case, where what we do is cube it, taking into account that we use a string for the iteration and therefore the index starts at 0 and the iteration numbers come and it is similar to the previous example:

We obtain the index and the following result:
0 0
1 1
2 8
3 27
The function "enumerate” gives us many advantages and can be used for various processes, which we are not going to detail here and I encourage you to explore.
It may be thought that it requiresrange” to manipulate parallel iterables, such as coordinates. Let's look at an example, where the strings X and Y store the coordinates of two-dimensional points.
In this case, if we write the code like this:

We obtain a coordinate system whose result is:
1 B
2 a
If we want to go deeper we have other possibilities, like this other simple example, in which we use tuples:

We get a result like this:
('Name', 'John')
('First surname', 'Lopez')
('Middle last name', 'Garcia')
We see that Python allows us multiple ways to do the same thing and referring to the zen of Python (import this) we can say: “Now is better than never.”