dictionary shared between objects for no reason?

后端 未结 4 1360
情书的邮戳
情书的邮戳 2021-01-22 18:59

The following code is supposed to create a new (modified) version of a frequency distribution (nltk.FreqDist). Both variables should then be the same length.

It works f

相关标签:
4条回答
  • 2021-01-22 19:35

    It works fine when a single instance of WebText is created. But when multiple WebText instances are created, then the new variable seems to be shared by all the objects.

    Well, yes; of course it would work fine with a single instance when all one of them is sharing the value. ;)

    The value is shared because Python follows a very simple rule: the things you define inside the class block belong to the class. I.e., they don't belong to instances. To attach something to an instance, you have to do it explicitly. This is normally done in __init__, but in normal cases (i.e. if you haven't used __slots__) can be done at any time. Assigning to an attribute of an object is just like assigning to an element of a list; there are no real protections because we're all mature adults here and are assumed to be responsible.

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

    Alternately:

    def __init__(self, text):
        freq_dist_weighted = {}
        # prepare the dictionary contents first
        self.freq_dist_weighted = freq_dist_weighted
    
    0 讨论(0)
  • 2021-01-22 19:39
    class WebText:
        freq_dist_weighted = {}
    

    declares freq_dist_weighted so that it is shared between all objects of type WebText; essentially, this is like a static member in C++.

    If you want each WebText object to have its own freq_dist_weighted member (i.e. you can change it for one instance without changing it for another instance), you want to define it in __init__:

    class WebText:
        def __init__(self):
            self.freq_dist_weighted = {}
    
    0 讨论(0)
  • 2021-01-22 19:42

    Your comment is blatantly wrong. Objects in a class scope are only initialized when the class is created; if you want a different object per instance then you need to move it into the initializer.

    class WebText:
        def __init__(self, text):
            self.freq_dist_weighted = {} #### RESET the dictionary HERE ####
             ...
    
    0 讨论(0)
  • 2021-01-22 19:51

    Your freq_dist_weighted dictionary is a class attribute, not an instance attribute. Therefore it is shared among all instances of the class. (self.freq_dist_weighted still refers to the class attribute; since there's no instance-specific attribute of that name, Python falls back to looking on the class.)

    To make it an instance attribute, set it in your class's __init__() method.

    def __init__(self, text):
        self.freq_dist_weighted = {}
        ...
    
    0 讨论(0)
提交回复
热议问题