2014-04-19 9 views
30

Ho il seguente codicestr.translate dà TypeError - Tradurre accetta un argomento (2 dato), ha lavorato in 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))])))]) 

ho testato le linee 2-4 in un file separato quando testing.py ho scritto

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 

e il comando restituisce prompt [ 'la', 'la', 'il'], che è quello che volevo (la rimozione di punteggiatura).

Tuttavia, quando ho messo il codice esattamente lo stesso in un file diverso, python restituisce un TypeError affermando che

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 è una lista di tutti i percorsi dei file (ho stampato e verificare che questa lista è valida). Sono confuso su questo TypeError perché tutto funziona perfettamente quando sto testandolo in un file diverso.

+1

Forse questo avviene perché un'altra codifica (utf8 per esempio) è usato in questo file, per cui la funzione translate ottiene solo un argomento. Non sono sicuro, ma è possibile? È possibile controllare questo stampando il tipo (lista di parole) per ogni caso. – Thorben

+0

Puoi mostrare le istruzioni di importazione? Forse c'è una funzione di traduzione che stai inconsapevolmente importando. Prova "print translate" quando ottieni l'eccezione e vedi quale modulo proviene da – Spaceghost

+0

@Spaceghost, le istruzioni di importazione sono: 'import nltk, os, json, csv, string, cPickle'' da scipy.stats import scoreatpercentile (2 righe separate) ' – carebear

risposta

55

Sospetto che il tuo problema abbia a che fare con le differenze tra str.translate e unicode.translate (queste sono anche le differenze tra str.translate su Python 2 rispetto a Python 3). Sospetto che il tuo codice originale sia stato inviato alle istanze unicode mentre il codice di test utilizza le istanze regolari a 8 bit str.

Non è consigliabile convertire le stringhe Unicode nelle normali istanze str, poiché unicode è un tipo molto migliore per la gestione dei dati di testo (ed è il futuro!). Invece, dovresti semplicemente adattarti alla nuova sintassi unicode.translate. Con il normale str.translate (su Python 2), è possibile passare un argomento opzionale deletechars e i caratteri in esso verranno rimossi dalla stringa. Per unicode.translate (e str.translate su Python 3), l'argomento extra non è più consentito, ma le voci della tabella di conversione con None come valore verranno eliminate dall'output.

Per risolvere il problema è necessario creare una tabella di conversione appropriata. Una tabella di conversione è un mapping di dizionario da ordinali Unicode (ovvero, int s) a numeri ordinali, stringhe o None. Una funzione di supporto per farli esiste in Python 2 come string.maketrans (e in Python 3 come metodo del tipo str), ma la versione Python 2 non gestisce il caso che ci interessa (inserendo i valori None nella tabella). Puoi creare autonomamente un dizionario appropriato con qualcosa come {ord(c): None for c in string.punctuation}.

33

Se tutti si sta cercando di realizzare è quello di fare la stessa cosa stavi facendo in Python 2 in Python 3, qui è quello che stavo facendo in Python 2.0 di buttare via la punteggiatura e numeri:

text = text.translate(None, string.punctuation) 
text = text.translate(None, '1234567890') 

qui è il mio equivalente Python 3.0:

text = text.translate(str.maketrans('','',string.punctuation)) 
text = text.translate(str.maketrans('','','1234567890')) 

In sostanza si dice 'tradurre nulla a nulla' (primi due parametri) e tradurre qualsiasi punteggiatura o numeri per None (cioè rimuoverli).

+1

Questa è la risposta corretta in Python3, +1. – gented

+0

Fantastico, grazie! +1 –

+1

È possibile combinare queste due mappe, banalmente, usando 'text.translate (str.maketrans ('', '', string.punctuation + '1234567890'))' o anche meglio, con 'text.translate (str .maketrans ('', '', string.punctuation + string.digits)) '. Memorizzerei la mappa di traduzione prima in una costante separata e riutilizzarla. –

1

Python 3.0:

text = text.translate(str.maketrans('','','1234567890')) 

str statica.maketrans (x [, y [, z]])

Questo metodo statico restituisce una tabella di conversione utilizzabile per str.translate().

Se c'è un solo argomento, deve essere un dizionario mappatura Unicode ordinali (interi) o caratteri (stringhe di lunghezza 1) a Unicode ordinali, stringhe (di lunghezza arbitraria) o None. Le chiavi dei caratteri verranno quindi convertite in ordinali.

Se sono presenti due argomenti, devono essere stringhe di uguale lunghezza e nel dizionario risultante, ciascun carattere in x verrà mappato sul carattere nella stessa posizione in . Se c'è un terzo argomento, deve essere una stringa, i cui caratteri verranno mappati su None nel risultato.

https://docs.python.org/3/library/stdtypes.html?highlight=maketrans#str.maketrans

Problemi correlati