Jan Pisl
Jan Pisl

Reputation: 1193

Why is a variable an int in one instance and a string in another depending on what I compare it to?

This code:

values = ("xdr_s1_18021664256", "xdr_s1_18021664257", "xdr_s1_18021664258","xdr_s1_18021664259")

list_of_strings = []
string_with_highest_number = ''
max_value = 0
print(type(max_value))
for i in values:
    x = i.split("_")[-1] 
    if x > max_value:
        max_value = i
        string_with_highest_number = i
print(string_with_highest_number)

Yields this error:

<class 'int'>
Traceback (most recent call last):
  File "test_delete.py", line 9, in <module>
    if x > max_value:
TypeError: '>' not supported between instances of 'str' and 'int'

x is a string and max_value integer. I cannot compare these two. Makes sense. So, I change the type of x to integer. So, the code looks like this:

values = ("xdr_s1_18021664256", "xdr_s1_18021664257", "xdr_s1_18021664258","xdr_s1_18021664259")

list_of_strings = []
string_with_highest_number = ''
max_value = 0
print(type(max_value))
for i in values:
    x = i.split("_")[-1] 
    if int(x) > max_value:
        max_value = i
        string_with_highest_number = i
print(string_with_highest_number)

And, to my surprise, this time it yields this error:

<class 'int'>
Traceback (most recent call last):
  File "test_delete.py", line 9, in <module>
    if int(x) > max_value:
TypeError: '>' not supported between instances of 'int' and 'str'

So, when I check the type of max_value before the loop, it is an integer. But then I get an error saying max_value is a string!

Can someone explain why this happens?

Upvotes: 0

Views: 66

Answers (3)

abarnert
abarnert

Reputation: 365717

After printing the type of max_value, you then reassign it to something different:

max_value = i

Since i names a string, max_value now names that same string. So, next time through the loop, when you do this:

if int(x) > max_value:

… it fails, because max_value is a string.


What you probably wanted to do was convert the value to an int before storing it, just as you convert the other value to an int before comparing:

if int(x) > max_value:
    max_value = int(i)

You may be confused because you're thinking in terms of something more like C++.

In C++, a variable is a typed slot where values live. When you assign to a variable, you're casting the value to that type and then copying it into the slot in memory. None of that is true in Python.

In Python, variables aren't slots in memory, they're just names for values that live wherever they want to live. When you assign to a variable, you're just making the variable another name for that value. There's no automatic casting like in C++. And there's no types for variables—any variable can hold any value.

It is often confusing to assign values of unrelated types to the same variable at different times. You can use a static type checker like Mypy, or a linter, or another kind of static analyzer to point out the potential confusion, if you find yourself doing this often.


You may also be confused because you're thinking of something more like Scheme. In Scheme, variables are just names for values, but you usually don't rebind them. You can, but more commonly you shadow them with a more local binding, and the binding is still there, hiding further up the stack. I don't think this is your issue here, so I won't explain further.

Upvotes: 4

Ryan Schaefer
Ryan Schaefer

Reputation: 3120

values = ("xdr_s1_18021664256", "xdr_s1_18021664257", "xdr_s1_18021664258","xdr_s1_18021664259")

list_of_strings = []
string_with_highest_number = ''
max_value = 0
print(type(max_value))
for i in values:
    x = i.split("_")[-1] 
    if int(x) > max_value:
        max_value = i // problem occurs here
        string_with_highest_number = i
print(string_with_highest_number)

Your problem is occuring when you assign i to max_value. After the first time it is run max_value receives the value "xdr_s1_18021664256" which is a string. You should assign max value to int(x).

Upvotes: 0

pault
pault

Reputation: 43504

There is a simpler way to find the max by passing a lambda function as the key to max():

max(values, key=lambda x: int(x.split("_")[-1]))
#'xdr_s1_18021664259'

Upvotes: 1

Related Questions