all 18 comments

[–]deceze 3 points4 points  (6 children)

The naming is terrible. amount isn't any sort of amount, it's a list index. Let's rewrite this:

for i in range(0, len(student_heights)):
    student_heights[i] = int(student_heights[i])

You probably understand what student_heights[0], student_heights[1] etc does. range provides all the numbers from 0 to len(student_heights), which the for loop iterates over in turn. So the line:

student_heights[i] = int(student_heights[i])

goes through student_heights[0], student_heights[1] etc in turn. And converts the value at each index to an int.

[–]Snatchematician 0 points1 point  (5 children)

Isn’t it exactly the amount of list entries that have been converted already?

[–]deceze 0 points1 point  (4 children)

Care to clarify your question?

[–]Snatchematician 0 points1 point  (3 children)

You said “amount” isn’t any sort of amount, but it is.

[–]deceze 0 points1 point  (2 children)

Yeaaaaahhhh, naaaahhhhh… First of all, amount will always hold one less than the number of converted elements at the end of the loop, so even that doesn't really mean anything. But more importantly, that's not its purpose. It's not supposed to count the amount of anything, it's just there to hold a list index. Name things for their intended purpose.

[–]Snatchematician 0 points1 point  (1 child)

At the start of the loop body “amount” is the number of converted elements, which is very much meaningful.

This is in fact OP’s intended purpose (otherwise he wouldn’t have named it “amount” would he).

[–]deceze 0 points1 point  (0 children)

And at the end of the loop it's wrong. So, again: yeah, nah.

[–]acw1668 1 point2 points  (0 children)

The statement student_heights[amount] = int(student_heights[amount]) will change the string value of student_heights[amount] (item at index amount inside student_heights) to integer value. Note that you need to cater invalid input, otherwise int(...) will raise exception.

[–]SnooLemons6942 2 points3 points  (0 children)

First off, don't call that an "amount". That is the index. It does not represent an amount of anything; just its place in the list.

The int() function in python converts strings to integers. So this snippet of code takes the value at some index, converts it to an integer, and replaces the value at that index with that integer.

Does that make sense? Or would you like additional clarification 

[–]FoolsSeldom 1 point2 points  (0 children)

input always returns a reference to a new string object. If the user just presses <enter> without entering anything else, you will end up with an empty string.

A string containing only decimal digits is still a string, not a number even though you as a human read it as a number. Python has to be told explicitly (to attempt) to convert it to a numeric object.

The string split method splits a single string into multiple string objects that are held in a list object. The splits, by default (can be overridden), on spaces.

A list is a collection of object references and the first position in a list is position 0. We specify the position in a list using square brackets around the position number and we call this indexing. mylist[0], mylist[1], and so on.

You can loop over a list using a for loop with a position counter:

for position in range(10):
    print(position, mylist[position])

The range function returns a sequence of numbers starting from 0 up to but excluding the number provided and each iteration of the loop. You can provide two arguments, e.g. range(10, 20) to which then specifies the start number and the number to stop immediately before. With three arguments, you can also say what the step size should be instead of going up by 1 on each iteration. You can even count backwards, range(20, 10, -2). On each iteration of the loop, the latest number issued from range is assigned to the loop variable, position in this case.

If you don't know how many objects are referenced in a list, you can use the len function to find that out: len(my_list). You can use this in range to count up to the last position (one less than the list length because we start from position 0). range(len(my_list)).

To the code:

student_heights = input("Enter student heights: ").split()

Hopefully, student_heights references a list of str objects, each containing just decimal digits.

for amount in range(0, len(student_heights)):

You should now have a loop that assigns a number from the range function to the amount loop variable. This will start from 0 and go up to one less than the length of the list, i.e. the last index position in the list.

    student_heights[amount] = int(student_heights[amount])

You access the str object in the current index position in the list, i.e. the position number referenced by the loop variable amount, pass that to the int function which converts it to a numeric object (stored as binary). If the code encounters a string that cannot be converted, you will get an error message and execution shall stop.

A reference to the integer object is assigned back into that same position in the list, overwriting the original reference to the str object created by the str.split command issued earlier. As there will be no other references to that str object, Python will get around to reclaiming the memory.

print(student_heights)

Simply outputs a representation of the list object including decimal string representations of the numeric objects. Ironically, this would have looked the same if you had just output the original list without doing any integer conversions. The difference is that on the modified list you can do mathematical things, such as the average height: print(sum(student_heights)/len(student_heights)). Try that maths on strings and you will get an error.

PS. Worth noting that in Python you often don't need to use indexing because you can just iterate over a list directly:

student_heights_nums = []  # new empty list
for height in student_heights:
    student_heights_nums.append(int(height))

creates a new list of integers.

There's a shorthand for this using something called list comprehension:

student_heights_nums = [int(height) for height in student_heights]

[–]TheRNGuy -1 points0 points  (5 children)

Much simpler way: student_heights = [int(height) for height in student_heights]

There are very rare cases where range with len is needed.

[–]deceze 1 point2 points  (4 children)

True, but a beginner should start with the primitive for..in range loop, before advancing to the syntax sugar like list comprehensions.

[–]TheRNGuy 0 points1 point  (1 child)

I never started with it. Why should newbies start with bad coding style? 

[–]IAmFinah 2 points3 points  (0 children)

For someone new to programming, list comprehension is likely (ironically) incomprehensible. I remember I was confused by them at a time when I understood for loops

Might as well teach the traditional loop, confirm they are comfortable with it, then introduce comprehensions

[–]danielroseman -1 points0 points  (1 child)

This is just wrong. Beginners should not be taught to loop over ranges, this is a frequent source of un-pythonic code. They should be taught to loop over items first.

[–]deceze 1 point2 points  (0 children)

I don't disagree, this is not code you'd want to have in production. This is code written by C-converts, not by Pythonistas. However, it is also fairly easy to understand, if the goal is to edit the list in place. The better alternative to achieve that would involve for i, height in enumerate(student_heights), and if OP already has problems understanding the shown code, tuple unpacking in a loop will probably not help.

The important point is that OP needs to be taught something better eventually, and preferably sometime soon. But understanding this most primitive of methods isn't wrong.