Thinking in terms of types, the original variable you have is of type List[int] ([1, 2, 3]).
When using the str function, the result is an element of type str (aka '[1, 2, 3]'), but that's not the result that you want since you want to convert each individual element in the list to str, which makes the desired type to be List[str] (['1', '2', '3']).
In python, there are several canonical ways to apply a function to each individual element:
List Comprehension
new_roll = [str(x) for x in roll] # ['1', '2', '3']
This method is the simplest. It is basically a one-liner that does the followings:
new_roll = []
for x in roll:
new_roll.append(str(x))
Notice that the original variable roll won't be mutated since it is creating a new list.
Map
Another way to do the same thing is by using the map function in python. However for efficiency reason, the type of the output is of type Map[str] instead of type List[str].
roll_map = map(str, roll)
for x in roll_map:
print(x)
It is basically doing the followings:
roll = [1, 2, 3]
for x in roll:
str_x = str(x)
print(str_x)
Notice that no new list has been created in order to save memory. This method is generally applicable when you need the result of a function applied to a list (or an iterator in general) but you do not want to store the results of the function application (to save memory).
A common hack to obtain a list via the map function is by list(map(str, roll)).
roll_str = [str(n) for n in roll]