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
class WebText:
    freq_dist_weighted = {}

声明freq_dist_weighted它在所有类型的对象之间共享WebText;本质上,这就像staticC++ 中的成员。

如果您希望每个WebText对象都有自己的freq_dist_weighted成员(即您可以为一个实例更改它而不为另一个实例更改它),您希望在以下位置定义它__init__

class WebText:
    def __init__(self):
        self.freq_dist_weighted = {}
于 2012-05-22T22:01:13.137 回答
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 回答