2

次のコードは、度数分布 (nltk.FreqDist) の新しい (変更された) バージョンを作成することになっています。両方の変数は同じ長さでなければなりません。

WebText の単一のインスタンスが作成されると、正常に機能します。しかし、複数の WebText インスタンスが作成されると、新しい変数はすべてのオブジェクトで共有されているように見えます。

例えば:

import nltk
from operator import itemgetter

class WebText:

    freq_dist_weighted = {}

    def __init__(self, text):
        tokens = nltk.wordpunct_tokenize(text) #tokenize
        word_count = len(tokens)
        freq_dist = nltk.FreqDist(tokens)


        for word,frequency in freq_dist.iteritems():
            self.freq_dist_weighted[word] = frequency/word_count*frequency
        print len(freq_dist), len(self.freq_dist_weighted)

text1 = WebText("this is a test")
text2 = WebText("this is another test")
text3 = WebText("a final sentence")

結果は

4 4
4 5
3 7

これは正しくありません。値を転置して変更しているだけなので、各列には同じ数値が含まれているはずです。ループの直前に freq_dist_weighted をリセットすると、正常に動作します。

import nltk
from operator import itemgetter

class WebText:

    freq_dist_weighted = {} 

    def __init__(self, text):
        tokens = nltk.wordpunct_tokenize(text) #tokenize
        word_count = len(tokens)
        freq_dist = nltk.FreqDist(tokens)
        self.freq_dist_weighted = {}

        for word,frequency in freq_dist.iteritems():
            self.freq_dist_weighted[word] = frequency/word_count*frequency
        print len(freq_dist), len(self.freq_dist_weighted)

text1 = WebText("this is a test")
text2 = WebText("this is another test")
text3 = WebText("a final sentence")

結果は(正しい):

4 4
4 4
3 3

これは私には意味がありません。

オブジェクト内で分離されているため、リセットする必要がある理由がわかりません。私は何か間違ったことをしていますか?

4

4 に答える 4

9

あなたのコメントはあからさまに間違っています。クラス スコープ内のオブジェクトは、クラスの作成時にのみ初期化されます。インスタンスごとに異なるオブジェクトが必要な場合は、それを初期化子に移動する必要があります。

class WebText:
    def __init__(self, text):
        self.freq_dist_weighted = {} #### RESET the dictionary HERE ####
         ...
于 2012-05-22T21:52:13.923 に答える
6

freq_dist_weightedディクショナリはクラス属性であり、インスタンス属性ではありません。したがって、クラスのすべてのインスタンス間で共有されます。(self.freq_dist_weighted引き続きクラス属性を参照します。その名前のインスタンス固有の属性がないため、Pythonはクラスの検索にフォールバックします。)

インスタンス属性にするには、クラスの__init__()メソッドで設定します。

def __init__(self, text):
    self.freq_dist_weighted = {}
    ...
于 2012-05-22T21:55:06.923 に答える
2

WebTextの単一インスタンスが作成されると正常に機能します。ただし、複数のWebTextインスタンスが作成されると、新しい変数はすべてのオブジェクトで共有されているように見えます。

はい、そうです; もちろん、すべてのインスタンスが値を共有している場合は、単一のインスタンスで正常に機能します。;)

Pythonは非常に単純なルールに従うため、値は共有されます。ブロック内で定義するものclassはクラスに属します。つまり、それらはインスタンスに属していません。インスタンスに何かをアタッチするには、明示的に行う必要があります。これは通常、で実行されます__init__が、通常の場合(つまり、使用していない場合__slots__)はいつでも実行できます。オブジェクトの属性への割り当ては、リストの要素への割り当てと同じです。私たち全員がここでは成熟した大人であり、責任があると想定されているため、本当の保護はありません。

def __init__(self, text):
    self.freq_dist_weighted = {}
    # and proceed to modify it

代わりに:

def __init__(self, text):
    freq_dist_weighted = {}
    # prepare the dictionary contents first
    self.freq_dist_weighted = freq_dist_weighted
于 2012-05-22T23:19:53.927 に答える
2
class WebText:
    freq_dist_weighted = {}

freq_dist_weightedtype のすべてのオブジェクト間で共有されるように宣言しWebTextます。基本的に、これはstaticC++ のメンバーのようなものです。

WebTextオブジェクトに独自のfreq_dist_weightedメンバーが必要な場合 (つまり、別のインスタンスで変更せずに 1 つのインスタンスで変更できる場合)、次のように定義します__init__

class WebText:
    def __init__(self):
        self.freq_dist_weighted = {}
于 2012-05-22T22:01:13.137 に答える