String Indices Must be Integers in Python - python

I am using Python to solve a contest problem. I am getting this error. I am fairly new and inexperienced with Python.
for kek in sorteddic:
lengthitem = int(len(kek))
questionstring = start[0, lengthitem]
kek is essentially the "item" in "sorteddic" which is an array of strings.
The error I am getting is:
questionstring = start[0, lengthitem]
TypeError: string indices must be integers
Can someone please help? Thanks.

It's because the item you're trying to use as an index, 0, lengthitem, is not an integer but a tuple of integers, as shown below:
>>> x = 1 : type(x)
<class 'int'>
>>> x = 1,2 : type(x)
<class 'tuple'>
If your intent is to get a slice of the array (not entirely clear but I'd warrant it's a fairly safe guess), the correct operator to use is :, as in:
questionstring = start[0:lengthitem]
or, since 0 is the default start point:
questionstring = start[:lengthitem]
The following transcript shows how your current snippet fails and the correct way to do it:
>>> print("ABCDE"[1])
B
>>> print("ABCDE"[1,3])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: string indices must be integers
>>> print("ABCDE"[1:3])
BC

Slice notation uses colons, not commas (unless you are in numpy where commas separate dimensions in slices, athough under the hood that is treated as a tuple of slice objects). So use:
questionstring = start[0:lengthitem]

Related

When I run this python command in the interpretor, I get a TypeError [duplicate]

I use a negative index in replacement fields to output a formatted list,but it raises a TypeError.The codes are as follows:
>>> a=[1,2,3]
>>> a[2]
3
>>> a[-1]
3
>>> 'The last:{0[2]}'.format(a)
'The last:3'
>>> 'The last:{0[-1]}'.format(a)
Traceback (most recent call last):
File "", line 1, in
TypeError: list indices must be integers, not str
It's what I would call a design glitch in the format string specs. Per the docs,
element_index ::= integer | index_string
but, alas, -1 is not "an integer" -- it's an expression. The unary-minus operator doesn't even have particularly high priority, so that for example print(-2**2) emits -4 -- another common issue and arguably a design glitch (the ** operator has higher priority, so the raise-to-power happens first, then the change-sign requested by the lower priority unary -).
Anything in that position in the format string that's not an integer (but, for example, an expression) is treated as a string, to index a dict argument -- for example:
$ python3 -c "print('The last:{0[2+2]}'.format({'2+2': 23}))"
The last:23
Not sure whether this is worth raising an issue in the Python trac, but it's certainly a somewhat surprising behavior:-(.
There are a few problems here, once you start digging:
The item in question is called "element_index" which is defined to be an integer.
Problem 1: unless users follow the link from "integer" to the language reference manual, they won't know that -1 is deemed to be an expression, not an integer. By the way, anyone tempted to say "works as documented" should see proplem 7 first :-)
Preferred solution: change the definition so that "element_index" can have an optional '-' before the integer.
It's an integer, right? Not so fast ... later the docs say that "an expression of the form '[index]' does an index lookup using __getitem__()"
Problem 3: Should say '[element_index]' (index is not defined).
Problem 4: Not everybody knows off the top of their heads what __getitem__() does. Needs clearer docs.
So we can use a dict here as well as an integer, can we? Yes, with a problem or two:
The element_index is a integer? Yes, that works with a dict:
>>> "{0[2]}".format({2: 'int2'})
'int2'
It seems that we can also use non-integer strings, but this needs more explicit documentation (Problem 5):
>>> "{0[foo]}".format({'foo': 'bar'})
'bar'
But we can't use a dict with a key like '2' (Problem 6):
>>> "{0[2]}".format({'2': 'str2'})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 2
>>> "{0['2']}".format({'2': 'str2'})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: "'2'"
Problem 7: That "integer" should really be documented to be "decimalinteger" ... 0x22 and 0b11 are treated as str, and 010 (an "octalinteger") is treated as 10, not 8:
>>> "{0[010]}".format('0123456789abcdef')
'a'
Update: PEP 3101 tells the true story:
"""
The rules for parsing an item key are very simple. If it starts with a digit, then it is treated as a number, otherwise it is used as a string.
Because keys are not quote-delimited, it is not possible to specify arbitrary dictionary keys (e.g., the strings "10" or ":-]") from within a format string.
"""
Correct, it does not work. solution:
>>> 'The last:{0}'.format(a[-1])
'The last:3'
I often take Python format strings as config options - with the format string provided with a specific, known list of keyword arguments. Therefore addressing the indexes of a variable length list forwards or backwards within the format string is exactly the kind of thing I end up needing.
I've just written this hack to make the negative indexing work:
string_to_tokenise = "Hello_world"
tokens = re.split(r"[^A-Z\d]+", string_to_tokenise, flags=re.I)
token_dict = {str(i) if i < 0 else i: tokens[i] for i in range(-len(tokens) + 1, len(tokens))}
print "{thing[0]} {thing[-1]}".format(thing=token_dict)
Result:
Hello world
So to explain, instead of passing in the list of tokens, I create a dictionary with all the required integer keys for indexing the list from 0 to len(..)-1, and I also add the negative integer keys for indexing from the end from -1 to -(len(..)-1), however these keys are converted from integers to strings, as that's how format will interpret them.

(Help) TypeError: 'str' object cannot be interpreted as an integer

Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
get_odd_palindrome_at('racecar', 3)
File "C:\Users\musar\Documents\University\Courses\Python\Assignment 2\palindromes.py", line 48, in get_odd_palindrome_at
for i in range(string[index:]):
TypeError: 'str' object cannot be interpreted as an integer
I want to use the value index refers to but how do I do that?
It seems from your error than the 'index' variable is a string, not an int. You could convert it using int().
index = int(index)
for i in range(string[index:]):
Now, string[index:] will also be an string. So you would need to convert that too:
>>> string = "5"
>>> range(string)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: range() integer end argument expected, got str.
>>> range(int(string))
[0, 1, 2, 3, 4]
>>>
That's assuming that string[index:] only contains a number. If that's not always the case, you can do something like:
# 'index' contains only numbers
index = int(index)
number = string[index:]
if number.isdigit():
number = int(number)
for i in range(number):
From the Wikipedia article on Python:
Python uses duck typing and has typed objects but untyped variable names. Type constraints are not checked at compile time; rather, operations on an object may fail, signifying that the given object is not of a suitable type. Despite being dynamically typed, Python is strongly typed, forbidding operations that are not well-defined (for example, adding a number to a string) rather than silently attempting to make sense of them.
In this case, you try to pass a string to range(). This function waits for a number (a positive integer, as it is). That's why you need to convert your string to int. You could actually do a bit more of checking, depending on your needs. Python cares for types.
HTH,

converting hex to int, the 'L' character [duplicate]

This question already has answers here:
Python Trailing L Problem
(5 answers)
Closed 9 years ago.
I have a 64bit hex number and I want to convert it to unsigned integer. I run
>>> a = "ffffffff723b8640"
>>> int(a,16)
18446744071331087936L
So what is the 'L' at the end of the number?
Using the following commands also don't help
>>> int(a,16)[:-1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'long' object is unsubscriptable
>>> int(a,16).rstrip("L")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'long' object has no attribute 'rstrip'
Python2.x has 2 classes of integer (neither of them are unsigned btw). There is the usual class int which is based on your system's concept of an integer (often a 4-byte integer). There's also the arbitrary "precision" type of integer long. They behave the same in almost1 all circumstances and int objects automatically convert to long if they overflow. Don't worry about the L in the representation -- It just means your integer is too big for int (there was an Overflow) so python automatically created a long instead.
It is also worth pointing out that in python3.x, they removed python2.x's int in favor of always using long. Since they're now always using long, they renamed it to int as that name is much more common in code. PEP-237 gives more rational behind this decision.
1The only time they behave differently that I can think of is that long's __repr__ adds that extra L on the end that you're seeing.
You are trying to apply string methods to an integer. But the string representation of a long integer doesn't have the L at the end:
In [1]: a = "ffffffff723b8640"
In [2]: int(a, 16)
Out[2]: 18446744071331087936L
In [3]: str(int(a, 16))
Out[3]: '18446744071331087936'
The __repr__ does, though (as #mgilson notes):
In [4]: repr(int(a, 16))
Out[4]: '18446744071331087936L'
In [5]: repr(int(a, 16))[:-1]
Out[5]: '18446744071331087936'
you can't call rstrip on an integer, you have to call it on the string representation of the integer.
>>> a = "ffffffff723b8640"
>>> b = int(a,16)
>>> c = repr(b).rstrip("L")
>>> c
'18446744071331087936'
Note however, that this would only be for displaying the number or something. Turning the string back into an integer will append the 'L' again:
>>> int(c)
18446744071331087936L

Python float list of list value comparison

I have started to look into python and am trying to grasp new things in little chunks, the latest goal i set for myself was to read a tab seperate file of floats into memory and compare values in the list and print the values if difference was as large as the user specified. I have written the following code for it so far:
#! /usr/bin/env python
value = raw_input('Please enter a mass difference:')
fh = open ( "values" );
x = []
for line in fh.readlines():
y = [float for float in line.split()]
x.append(y)
fh.close()
for i in range(0,len(x)-1):
for j in range(i,len(x)):
if x[j][0] - x[i][0] == value:
print x[i][0],x[j][0]
The compiler complains that i am not allowed to substract strings from strings (logically) but my question is ... why are they strings? Shouldn't the nested list be a list of floats as i use float for float?
Literal error:
TypeError: unsupported operand type(s) for -: 'str' and 'str'
I would greatly appreciate if someone can tell me where my reasoning goes wrong ;)
Try this in place of your list comprehension:
y = [float(i) for i in line.split()]
Explanation:
The data you read from the file are strings, to convert them to other types you need to cast them. So in your case you want to cast your values to float via float() .. which you tried, but not quite correctly/successfully. This should give you the results you were looking for.
If you have other values to convert, this syntax will work:
float_val = float(string_val)
assuming that string_val contains valid characters for a float, it will convert, otherwise you'll get an exception.
>>> float('3.5')
3.5
>>> float('apple')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for float(): apple
The list comprehension isn't doing what you think it's doing. It's simply assigning each string to the variable float, and returning it. Instead you actually want to use another name and call float on it:
y = [float(x) for x in line.split()]
Error 1: y = [float(x) for x in line.split()] or simply map(float,lines.split())
Error 2: if x[j][0] - x[i][0] == float(value): #you didn't converted value to a float

Why does Python Array Module Process Strings and Lists Differently?

I'm having trouble understanding the result of the following statements:
>>> from array import array
>>> array('L',[0xff,0xff,0xff,0xff])
array('L', [255L, 255L, 255L, 255L])
>>> from array import array
>>> array('L','\xff\xff\xff\xff')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: string length not a multiple of item size
You are running this on a 64-bit build of Python, on which array treats type code 'L' as a 64-bit unsigned integer.
>>> array('L','\xff\xff\xff\xff\xff\xff\xff\xff')
array('L', [18446744073709551615L])
The documentation isn't very clear. All it says is that 'L' is at least four bytes.
In the first case you are initializing the array from a list with 4 elements. That will give you an array with 4 elements: one for each value in the list.
In the second case you are initializing the array from a byte string: the bytes in the string will be copied directly into the array. The 'L' specifier creates an array of unsigned longs which have a minimum size of 4 bytes.
On my machine (Windows 64 bit Python 2.6) initializing from a 4 byte string works fine:
>>> a = array('L','\xff\xff\xff\xff')
>>> a.tostring()
'\xff\xff\xff\xff'
I guess whichever version of Python you are using has unsigned longs that are 8 bytes rather than 4. Try converting the array you created from a list back to a string and see how many bytes that contains:
>>> a = array('L',[0xff,0xff,0xff,0xff])
>>> a.tostring()
'\xff\x00\x00\x00\xff\x00\x00\x00\xff\x00\x00\x00\xff\x00\x00\x00'
P.S. I'm assuming that you are using Python 2.x, on Python 3.x you would have got a TypeError instead.

Categories

Resources