简体   繁体   中英

TypeError: unsupported operand type(s) for -: 'str' and 'int'

Right now my code will create a text file including the positions of each word in a sentence in a list, and each word in a list - like so:

文件内容

My code then opens back up the file and should be able to recreate the sentence using those positions and the words in the text file, but it doesn't seem to work with with the readlines code for some reason.

openfilename = open(openfilename,"r")
readlines = openfilename.readlines()

wordslist = readlines[0]
positionslist = readlines[1]

print(positionslist)
print(wordslist)

originalsentence = " ".join([wordslist[x-1] for x in positionslist])
print(originalsentence)

For example this comes up with wordslist and positionslist coming out as:

[1, 2, 3, 2]
['test123', ',', '.']

Where as if I were to use:

positionslist = [1, 2, 3, 2]
wordslist = ['test123', ',', '.']
originalsentence = " ".join([wordslist[x-1] for x in positionslist])
print(originalsentence)

It would work, and I have no idea why because, as a newcomer to python, you'd think they'd work the same. Looking at other people's post with the same error I'm supposedly missing a

(int(...)

line of code somewhere but I'm not sure where, or if that's even the problem.

EDIT: this answer assumes a "raw" format. It won't work here. It would work if readlines[1] was already a list of strings obtained by splitting a line like "1 4 5 6 7" , which isn't the case here since line contains a python list written as a str(list) . ast.literal.eval is the right choice in that case, if the input format is satisfying and not a mistake in the first place.

when you do:

positionslist = readlines[1]

there's no way you get something other than a list of strings containing integers. You have to convert them for example like this:

positionslist = [int(x) for x in readlines[1]]

In your hardcoded example, you're using integers directly and it works.

Note: as cricket_007 suggested, since you just iterate on positionslist , you can use

positionslist = map(int,readlines[1])

It applies the int function to each item of readlines[1] , returns an iterable (returns list in Python 2, so not that much different from the list comprehension above in that case).

In Python 3, that avoids to create/allocate a list that you don't need since you don't use indexes (if you want to debug it you can't since you can iterate only once on it), so it is more performant.

of course, if some line is not a digit it will crash with an explicit error ValueError: invalid literal for int() with base 10

Another solution is to use ast.literal_eval() to convert your string u'[1, 2, 3, 2] directly into a list of interger:

import ast

with open(openfilename, "r") as f:
    positionslist = ast.literal_eval(f.readline())
    wordslist = ast.literal_eval(f.readline())

    print(" ".join([wordslist[x-1] for x in positionslist]))

Also, the with statement replace a try and catch. It also automatically close the file after the block.

The issue is, when you read from the file, the values are of str type by default. And when you try to do x-1 in [wordslist[x-1] for x in positionslist] , you get error because you try to subtract 1 from string. In order to fix this, convert positionslist to list of int's as:

positionslist = readlines[1]
positionslist = map(int, positionslist) # <-- add this line in your code 

and your code will work. Check map() to know about it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM