I think one of the most important concepts in computer science learning is to understand how array indexing works. You should spend some time explaining this concept to the students, in a lucid manner with simple examples. Since LISP, almost all programming languages start with Zero-based numbering. Python and C++ are no different. In Python, simple lists
can be used as examples to illustrate the concept.
#a simple list
In [15]: list1 = [1,2,3,4,5,6,7,8,9,10,11]
In [23]: len(list1) #number of items in the list
Out[23]: 11
In [26]: list1[0] #the first item in the list
Out[26]: 1
In [25]: print("list1 starts at index {}. The number at this index is {}.".format(list1.index(1), list1[0]))
list1 starts at index 0. The number at this index is 1.
In [37]: list1[10] #the last item in the list
Out[37]: 11
In [19]: print("list1 ends at index {}. The number at this index is {}.".format(len(list1)-1, list1[-1]))
list1 ends at index 10. The number at this index is 11.
As you will observe, the 'number' values are ahead of the 'index' values by 1
. What if the list list1
started with 0 and ended with 11, then the index values and 'number' values would be the same but the number of items in the list will increase by 1
and this is because we included 0. Hold that thought for a moment as we'll need this:
In [29]: list2 = [0,1,2,3,4,5,6,7,8,9,10,11]
In [31]: len(list2) #total number of items in list
Out[31]: 12
In [32]: list2[0]
Out[32]: 0
In [35]: list2[11]
Out[35]: 11
Remember the syntax for range()
according to the docs is: range(start, end, step)
. We will ignore step for this discussion.
So, now if I want to generate a similar list as list2
using range()
, I can use the above information to form a generalized syntax for range():
Syntax: range(start, len(list2)+start), where start is the first item in the range,
list2 is a list and len(list2) is its size and the end is len(list2) + start
To get this into a list, I simply pass the above as an argument to the list()
function. Its not important to get into the nitty gritty of this function, and used only for illustration. Thus, we get:
In [39]: list3 = list(range(0,len(list2)+0))
In [40]: list3
Out[40]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
In [41]: list2 == list3 #both lists are equivalent
Out[41]: True
In [42]: len(list3)
Out[42]: 12 #same number of items as list2
In [46]: for i in range(0,len(list3)+0): #can replace list3 with list2 to get same results
...: print(i, end=' ')
...:
0 1 2 3 4 5 6 7 8 9 10 11 #Output
The for loop iterates by index positions. So, i
starts at index position 0 for item 0(start of range) and goes on till index position 11 for item 11(end of range = 11 + 0).
We can also verify the above syntax for list1
that has start as 1 and length as 11.
In [6]: list(range(1,len(list1)+1))
Out[6]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] #same as list1 above
In [15]: for i in range(1,len(list1)+1):
...: print(i, end=' ')
...:
1 2 3 4 5 6 7 8 9 10 11
Again, the for-loop start at index position 0 as usual which has item 1(start of range) and ends at index position 10 which has item 11(end of range = 11 + 1).
Now, let's look at how this concept also applies to C++. We use the same list2
which has 12 items ,i.e. len(list2) = 12
. Again, its not important to get into the details of everything in the following example if the students are not quite familiar with arrays. This is just for illustration purposes:
#include <iostream>
using namespace std;
int main()
{
int list2[12] = {0,1,2,3,4,5,6,7,8,9,10,11};
std::cout << "Length of array list2 = " << (sizeof(list2)/sizeof(*list2)) << std::endl;
for(int i=0;i<(sizeof(list2)/sizeof(*list2));i++)
{
cout<<i<<' ';
}
return 0;
}
//Output:
Length of array list2 = 12
0 1 2 3 4 5 6 7 8 9 10 11 #Output
Notice i<(sizeof(list2)/sizeof(*list2))
makes sure that the final item is retrieved from the upper bound of the array, i.e. item 11 from index=12-1=11. This is exactly what the range()
function does. If I do i<=(sizeof(list2)/sizeof(*list2))
, that would also print 12 in the output which is not an item in list2
and will go beyond the array's upper bound. In Python, the range()
function is more explicit about the array boundaries. So, if I override the range()
syntax above and allow the for loop to iterate from 0 to an item beyond list2
by incrementing end by 1, I can print that item explicitly:
In [13]: for i in range(0,len(list2)+1):
...: if i>=len(list2):
...: print("\nI am outside of list2: {}".format(i))
...: else:
...: print(i, end=' ')
...:
0 1 2 3 4 5 6 7 8 9 10 11
I am outside of list2: 12
What we understand from this discussion is that it is important to understand for-loop iteration as an index-based operation and the range(start,end)
is a Python built-in function that merely composes values between the start & end range, inclusive of the start value and exclusive of the end value. Consider the total number of values traversed including the item at start(len(total) + start
) as the end of the range. The for-loop implementation is independent of this and only considers index positions both in Python and C++.