str.translate 报 TypeError - Translate 只需一个参数(给了两个),在 Python 2 中正常工作

61 投票
4 回答
81317 浏览
提问于 2025-04-18 03:26

我有以下这段代码:

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 个回答

0

如果你只是想实现类似这样的功能:"123hello.jpg".translate(None, 0123456789"),那么可以试试下面这个:

 "".join(c for c in "123hello.jpg" if c not in "0123456789")

输出结果:hello.jpg

7

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

74

我觉得你的问题可能和 str.translateunicode.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} 这样的方式。

121

如果你只是想在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(也就是删除它们)。

撰写回答