I don't understand how ev_range = row[1] knows to change the strings in the second column of each row to an integer

Question:

ev_data = [['vehicle', 'range', 'price'],
       ['Tesla Model 3 LR', '310', '49900'],
       ['Hyundai Ioniq EV', '124', '30315'],
       ['Chevy Bolt', '238', '36620']]
for row in ev_data[1:]:
    ev_range = row[1]
    ev_range = int(ev_range)
    row[1] = ev_range

print(ev_data)

Im currently a beginner learning and I don’t understand this concept of how ev_range = row[1] changes the second strings in each row to an integer.

How does the variable row which could be anything including row know to change the second string in each row to an integer.
Trying to get as firm understanding cuz it helps me learn the concepts and how to use them better as well as remember them.

Asked By: NolongerHuman

||

Answers:

The point of this code is to convert the range column from a string to an integer. The problem is that the first row is a header and should not be converted. So, the code makes a temporary list that skips the first row, and does the conversion from there.

ev_data is a list of lists. ev_data[1:] makes a copy of the outer list, skipping the first row ['vehicle', 'range', 'price']. This new list holds additional references to the existing inner lists ['Tesla Model 3 LR', '310', '49900'], and etc… The for loop iterates each of these lists. Remember that these are just additional references to the existing inner lists, so row[1] = ev_range will assign back to those lists. Notice that ev_range = row[1] didn’t change the row. ev_range is a temporary variable and its assignment back to row[1] is what makes the change in the inner lists.

If we print the identifiers of the original list, we can see how values in each one are reassigned in turn.

ev_data = [['vehicle', 'range', 'price'],
       ['Tesla Model 3 LR', '310', '49900'],
       ['Hyundai Ioniq EV', '124', '30315'],
       ['Chevy Bolt', '238', '36620']]

print("inner lists:")
for row in ev_data:
    print("  ", id(row))

print("conversion:")
for row in ev_data[1:]:
    ev_range = row[1]
    ev_range = int(ev_range)
    print("  ", id(row), repr(row[1]), "-->", ev_range)
    row[1] = ev_range

print(ev_data)

Result

inner lists:
   140508916540288
   140508916617216
   140508915115712
   140508915114432
conversion:
   140508916617216 '310' --> 310
   140508915115712 '124' --> 124
   140508915114432 '238' --> 238
[['vehicle', 'range', 'price'], ['Tesla Model 3 LR', 310, '49900'], ['Hyundai Ioniq EV', 124, '30315'], ['Chevy Bolt', 238, '36620']]
Answered By: tdelaney

ev_range = row[1] binds the second item in row (which in this case is always a str object) to the variable ev_range. Strings in python are immutable as are integers, their values can not change. If you bind (assign) another value to either row[1] or ev_range it will be a different object rather than modifying the value of the string itself.

Afterward the line ev_range = int(ev_range) causes string value already bound to ev_range to be replaced with the corresponding integer value. For example "310" would become 310, however if you had a string like "not digits" it would raise an Exception.

Finally the assignment row[1] = ev_range binds the integer to the second element of row (unlike in the case of the string python intepreters usually take a short cut for low common integers like 3 and just use the same object, such that any variable with the value 3 will be bound to the one immutable object 3). The string object for "310" or whichever no longer is bound to anything and is destroyed by garbage collection at this point.

Answered By: Andrew Allaire
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.