str.translate 报 TypeError - Translate 只需一个参数(给了两个),在 Python 2 中正常工作
我有以下这段代码:
import nltk, os, json, csv, string, cPickle
from scipy.stats import scoreatpercentile
lmtzr = nltk.stem.wordnet.WordNetLemmatizer()
def sanitize(wordList):
answer = [word.translate(None, string.punctuation) for word in wordList]
answer = [lmtzr.lemmatize(word.lower()) for word in answer]
return answer
words = []
for filename in json_list:
words.extend([sanitize(nltk.word_tokenize(' '.join([tweet['text']
for tweet in json.load(open(filename,READ))])))])
我在一个叫 testing.py 的单独文件中测试了第2到第4行代码,当我写了:
import nltk, os, json, csv, string, cPickle
from scipy.stats import scoreatpercentile
wordList= ['\'the', 'the', '"the']
print wordList
wordList2 = [word.translate(None, string.punctuation) for word in wordList]
print wordList2
answer = [lmtzr.lemmatize(word.lower()) for word in wordList2]
print answer
freq = nltk.FreqDist(wordList2)
print freq
命令提示符返回了 ['the','the','the'],这正是我想要的(去掉了标点符号)。
但是,当我把完全相同的代码放到另一个文件里时,Python 返回了一个类型错误(TypeError),提示:
File "foo.py", line 8, in <module>
for tweet in json.load(open(filename, READ))])))])
File "foo.py", line 2, in sanitize
answer = [word.translate(None, string.punctuation) for word in wordList]
TypeError: translate() takes exactly one argument (2 given)
json_list 是一个包含所有文件路径的列表(我打印出来检查过,这个列表是有效的)。我对这个类型错误感到困惑,因为在我测试的那个不同文件里,一切都运行得很好。
4 个回答
如果你只是想实现类似这样的功能:"123hello.jpg".translate(None, 0123456789")
,那么可以试试下面这个:
"".join(c for c in "123hello.jpg" if c not in "0123456789")
输出结果:hello.jpg
Python 3.0:
text = text.translate(str.maketrans('','','1234567890'))
static str.maketrans(x[, y[, z]])
这个静态方法会返回一个翻译表,可以用在
str.translate()
方法中。
如果只有一个参数,它必须是一个字典,这个字典把 Unicode 编码(整数)或者字符(长度为1的字符串)映射到 Unicode 编码、字符串(任意长度)或者 None
。字符作为键会被转换成对应的编码。
如果有两个参数,它们必须是长度相同的字符串,生成的字典中,x
中的每个字符会被映射到 y
中相同位置的字符。如果有第三个参数,它必须是一个字符串,这个字符串中的字符会在结果中被映射为 None
。
https://docs.python.org/3/library/stdtypes.html?highlight=maketrans#str.maketrans
我觉得你的问题可能和 str.translate
和 unicode.translate
之间的区别有关(这也是 Python 2 和 Python 3 中 str.translate
的不同之处)。我猜你的原始代码使用的是 unicode
实例,而你的测试代码则使用的是普通的 8 位 str
实例。
我不建议把 Unicode 字符串转换回普通的 str
实例,因为 unicode
是处理文本数据的更好选择(而且它是未来的趋势!)。相反,你应该适应新的 unicode.translate
语法。在 Python 2 中,使用普通的 str.translate
时,你可以传递一个可选的 deletechars
参数,里面的字符会从字符串中删除。而在 unicode.translate
(以及 Python 3 中的 str.translate
)中,不再允许这个额外的参数,但如果翻译表中的某个条目值为 None
,那么这个字符就会从输出中删除。
要解决这个问题,你需要创建一个合适的翻译表。翻译表就是一个字典,它将 Unicode 编码(也就是 int
类型)映射到其他编码、字符串或 None
。在 Python 2 中,有一个帮助函数叫 string.maketrans
来生成翻译表(在 Python 3 中是 str
类型的方法),但 Python 2 版本的这个函数不处理我们关心的情况(即在表中放入 None
值)。你可以自己构建一个合适的字典,比如用 {ord(c): None for c in string.punctuation}
这样的方式。
如果你只是想在Python 3中做和Python 2一样的事情,这里是我在Python 2.0中用来去掉标点符号和数字的代码:
text = text.translate(None, string.punctuation)
text = text.translate(None, '1234567890')
这是我在Python 3.0中对应的代码:
text = text.translate(str.maketrans('','',string.punctuation))
text = text.translate(str.maketrans('','','1234567890'))
基本上,这段代码的意思是“把什么都不翻译成什么”(前两个参数),然后把任何标点符号或数字翻译成None
(也就是删除它们)。