I am trying to step through a list of lists operating on each element of each list using nested for loops. I am getting a warning from PyCharm that the type of the counter in the second for loop is not certain to be an integer, despite it is derived from a range value. The code executes correctly, by why the warning?
def get_vote_fraction(cl_count, ag_vector):
v_f_vector = [[0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0, 0]]
for b in range(0, len(v_f_vector)):
for c in range(0, len(v_f_vector[b])):
v_f_vector[b][c] = f"{(ag_vector[b][c] / cl_count): .2F}"
return v_f_vector
aggregated_vector = [[0, 8, 0, 6], [0, 1, 0, 0, 0, 0, 9, 0], [0, 0, 10, 0], [0, 10, 0, 0, 0]]
class_count = 10
vote_fraction = get_vote_fraction(class_count, aggregated_vector)
print(vote_fraction)
As expected the output is [[' 0.00', ' 0.80', ' 0.00', ' 0.60'], [' 0.00', ' 0.10', ' 0.00', ' 0.00', ' 0.00', ' 0.00', ' 0.90', ' 0.00'], [' 0.00', ' 0.00', ' 1.00', ' 0.00'], [' 0.00', ' 1.00', ' 0.00', ' 0.00', ' 0.00']]
I get a warning that c in v_f_vector[b][c] can be of Unexpected type(s) (int, str) which says c is not sufficiently defined as an integer. I hesitate to raise an issue with PyCharm since I may be missing something simple. Anyone see what I am missing?
The “TypeError: 'str' object cannot be interpreted as an integer” error is raised when you pass a string as an argument into a range() statement. To fix this error, make sure all the values you use in a range() statement are integers.
The Python "TypeError: 'list' object cannot be interpreted as an integer" occurs when we pass a list to a function that expects an integer argument, e.g. range() . To solve the error, either pass the length of the list, e.g. len(my_list) or pass an integer to the function.
You can check if a number is present or not present in a Python range() object. To check if given number is in a range, use Python if statement with in keyword as shown below. number in range() expression returns a boolean value: True if number is present in the range(), False if number is not present in the range.
Regarding the PyCharm warning (that the question is all about)
Although the 2nd index (c) is highlighted, making users think it is the problem, it's not about that, at all.
Generally, lists are homogeneous containers, meaning that they contain elements of the same type.
PyCharm evaluated v_f_vector as being a list of lists of ints (and thus v_f_vector[b][c]
as an int). Trying to assign a string to it, would kind of break the list homogeneity, hence the warning.
Try assigning dummy values (e.g. 0.01f
, ()
, []
, ...) to it, and the warning text will change, like in the image below:
As a quick (and dirty) workaround, if the lists are going to contain strings, you could do something like:
v_f_vector = [["", "", "", ""], ["", "", "", "", "", "", "", ""], ["", "", "", ""], ["", "", "", "", ""]]
Regarding the code that lead to this
Declaring a list with a certain content, and then coming back and changing that content (based on another (similar structural) list) is counter-intuitive.
Your (end) goal, can be achieved in one line of code (the most Pythonic form), consisting of a list comprehension (check [Python 3.Docs]: List Comprehensions). Since your list nesting level is 2, so will be the comprehension:
>>> aggregated_vector = [[0, 8, 0, 6], [0, 1, 0, 0, 0, 0, 9, 0], [0, 0, 10, 0], [0, 10, 0, 0, 0]] >>> class_count = 10 >>> >>> vote_fraction = [[f"{(item1 / class_count): .2F}" for item1 in item0] for item0 in aggregated_vector] >>> print(vote_fraction) [[' 0.00', ' 0.80', ' 0.00', ' 0.60'], [' 0.00', ' 0.10', ' 0.00', ' 0.00', ' 0.00', ' 0.00', ' 0.90', ' 0.00'], [' 0.00', ' 0.00', ' 1.00', ' 0.00'], [' 0.00', ' 1.00', ' 0.00', ' 0.00', ' 0.00']] >>> >>> # Or, if you REALLY need to have a function ... >>> def get_vote_fraction(cl_count, ag_vector): ... return [[f"{(item1 / cl_count): .2F}" for item1 in item0] for item0 in ag_vector] ... >>> >>> print(get_vote_fraction(class_count, aggregated_vector)) [[' 0.00', ' 0.80', ' 0.00', ' 0.60'], [' 0.00', ' 0.10', ' 0.00', ' 0.00', ' 0.00', ' 0.00', ' 0.90', ' 0.00'], [' 0.00', ' 0.00', ' 1.00', ' 0.00'], [' 0.00', ' 1.00', ' 0.00', ' 0.00', ' 0.00']]
Note: your code could be adapted as well, but I'd suggest to go with the recommended variant(s).
I think that the warning comes from the fact that you are replacing integer values with strings. When I tried to instanciate v_f_vector
with '0'
instead of 0
, PyCharm didn't show any warning:
v_f_vector = [['0', '0', '0', '0'], ['0', '0', '0', '0', '0', '0', '0', '0'], ['0', '0', '0', '0'], ['0', '0', '0', '0', '0']]
However, it may be not the best way to fix the problem. I would suggest such a refactoring of your code:
def get_vote_fraction(cl_count, ag_vector):
v_f_vector = []
for b in range(0, len(ag_vector)):
v_f_vector.append([])
for c in range(0, len(ag_vector[b])):
v_f_vector[b].append(f"{(ag_vector[b][c] / cl_count): .2F}")
return v_f_vector
aggregated_vector = [[0, 8, 0, 6], [0, 1, 0, 0, 0, 0, 9, 0], [0, 0, 10, 0], [0, 10, 0, 0, 0]]
class_count = 10
vote_fraction = get_vote_fraction(class_count, aggregated_vector)
print(vote_fraction)
It will allow you to change aggregated_vector
without reflecting these changes to instanciated v_f_vector
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With