1. ホーム
  2. パイソン

[解決済み] オブジェクトのタイプ 'generator' は len() を持ちません。

2022-03-03 12:19:10

質問

Pythonを学び始めたばかりです。NLTKでテキストをユニグラム、ビッググラムに分割するプログラムを書きたいと思っています。 例えば、入力テキストが...であるとします。

"I am feeling sad and disappointed due to errors"

... 私の関数は、次のようなテキストを生成する必要があります。

I am-->am feeling-->feeling sad-->sad and-->and disappointed-->disppointed due-->due to-->to errors

私は、プログラムにテキストを入力するコードを書きました。以下は、私が試している関数です。

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

エラーが出るのは...

for x in range(0, len(bigrams)):

TypeError: object of type 'generator' has no len()

として ngrams 関数はジェネレータを返すので、試しに len(list(bigrams)) が、0値を返すので、同じエラーが出ています。StackExchangeの他の質問も参考にさせていただきましたが、まだ解決方法がつかめません。このエラーで行き詰っています。何か回避策や提案があれば教えてください。

解決方法を教えてください。

セパレータで区切られた値を連結して文字列を構成するのは、以下の方法が最適です。 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))

なお、末尾に "-->" は付きませんので、必要であれば追加してください。こうすることで、使用するイテラブルの長さについて考える必要がなくなります。一般にpythonでは、ほとんどそうです。もし反復処理可能なものに対して反復処理を行いたい場合は for x in iterable: . インデックスが必要な場合は enumerate :

for i, x in enumerate(iterable):
    ...