字典无故对象之间共享?(dictionary shared between objects for

2019-07-29 12:44发布

下面的代码应该创建一个频率分布(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

这是没有道理给我。

我不明白为什么我会重置它,因为它的对象中分离出来。 难道我做错了什么?

Answer 1:

您的评论是公然错误的。 在一类范围中的对象创建类时仅初始化; 如果你想每个实例不同的对象,那么你需要将它移动到初始化。

class WebText:
    def __init__(self, text):
        self.freq_dist_weighted = {} #### RESET the dictionary HERE ####
         ...


Answer 2:

freq_dist_weighted字典是一个类属性,而不是一个实例属性。 因此,类的所有实例之间共享。 ( self.freq_dist_weighted还是指类属性;因为有那个名字没有特定实例的属性,巨蟒回落到找上了班。)

为了使实例属性,在类的设置__init__()方法。

def __init__(self, text):
    self.freq_dist_weighted = {}
    ...


Answer 3:

class WebText:
    freq_dist_weighted = {}

声明了freq_dist_weighted以便它类型的所有对象之间共享WebText ; 本质上,这是像一个static在C ++构件。

如果你希望每个WebText对象有它自己的freq_dist_weighted成员(即你可以换一个实例,而不改变它的另一个实例),你想将它定义__init__

class WebText:
    def __init__(self):
        self.freq_dist_weighted = {}


Answer 4:

创建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


文章来源: dictionary shared between objects for no reason?