web-dev-qa-db-fra.com

l'objet de type 'générateur' n'a pas de len ()

Je viens de commencer à apprendre le python. Je veux écrire un programme en NLTK qui décompose un texte en unigrammes, bigrammes. Par exemple, si le texte saisi est:

"Je me sens triste et déçu à cause d'erreurs"

La fonction doit générer du texte comme:

Je suis -> je me sens -> je me sens triste -> triste et -> et déçu -> déçu à cause -> à cause de -> à des erreurs

J'ai écrit du code pour saisir du texte dans le programme. Voici la fonction que j'essaie:

def gen_bigrams(text):
    token = nltk.Word_tokenize(review)
    bigrams = ngrams(token, 2)
    #print Counter(bigrams)
    bigram_list = ""
    for x in range(0, len(bigrams)):
        words = bigrams[x]
        bigram_list = bigram_list + words[0]+ " " + words[1]+"-->"
    return bigram_list

L'erreur que je reçois est ...

for x in range(0, len(bigrams)):
TypeError: object of type 'generator' has no len()

Comme la fonction ngram retourne un générateur, j'ai essayé d'utiliser len(list(bigrams)) mais elle renvoie 0 valeur, donc j'obtiens la même erreur. J'ai fait référence à d'autres questions sur stackexchange, mais je ne sais toujours pas comment résoudre ce problème. Je suis coincé à cette erreur. Toute solution de contournement, suggestion?.

12
Vishal Kharde

Il est préférable de construire des chaînes en concaténant des valeurs séparées par un séparateur str.join :

def gen_bigrams(text):
    token = nltk.Word_tokenize(text)
    bigrams = nltk.ngrams(token, 2)
    # instead of " ".join also "{} {}".format would work in the map
    return "-->".join(map(" ".join, bigrams))

Notez qu'il n'y aura pas de "->" à la fin, alors ajoutez-le, si c'est nécessaire. De cette façon, vous n'avez même pas à penser à la longueur de l'itérable que vous utilisez. En général, en python c'est presque toujours le cas. Si vous voulez parcourir un itérable, utilisez for x in iterable:. Si vous avez besoin des index, utilisez enumerate :

for i, x in enumerate(iterable):
    ...
4
Ilja Everilä

bigrams est une fonction de générateur et bigrams.next () est ce qui vous donne le Tuple de vos jetons. Vous pouvez faire len () sur bigrams.next () mais pas sur la fonction générateur. Voici un code plus sophistiqué pour faire ce que vous essayez de réaliser.

>>> review = "i am feeling sad and disappointed due to errors"
>>> token = nltk.Word_tokenize(review)
>>> bigrams = nltk.ngrams(token, 2)
>>> output = ""
>>> try:
...   while True:
...     temp = bigrams.next()
...     output += "%s %s-->" % (temp[0], temp[1])
... except StopIteration:
...   pass
... 
>>> output
'i am-->am feeling-->feeling sad-->sad and-->and disappointed-->disappointed due-->due to-->to errors-->'
>>> 
1
MohitC