Lists are weird when they are instance members

Troels Therkelsen t_therkelsen at hotmail.com
Sun Jan 4 00:03:58 CET 2004


In article <ffHJb.5475$HL3.4277 at newssvr29.news.prodigy.com>, python newbie wrote:
> hey,
>  okay, I'm trying to figure out why my books: Quick Python, Python in a
> Nutshell, Python Cookbook and Learning Python don't say anything about the
> weird behavior of a list when you have one as an object instance member.
> 
> for instance (my first pun of 2004), if I have,
> 
> test.py
> ----------------
> 
>  global_filegroup_array = []  # array of filegroup objects
> 
>  class FileGroup:
>        a = 0
>        mylist = []      # here it is

mylist in this case is a class variable; what this means is that it is shared
amongst all *instances* of the class.  Only if an instance of the class rebinds
mylist is it local to the particular class instance doing this.

> 
>        def  put_stuff_in_my_list(self, anyfile):
>               self.mylist.append( get just a single string from file)   #
> pls excuse the psuedo

Because lists are mutable, when you use mylist.append(...) you don't rebind
mylist, but change its contents.  Since mylist is a class variable, this
change is available to the class as well as all instances of the class.

> 
>        def __init__(self):
>             put_stuff_in_my_list(anyfile)
> 
> def main():                         #     do ten times:  instantiate the
> above object, and add to the global array
>      for i in xrange(10):
>           filegroup = FileGroup()
>           global_filegroup_array.append(filegroup)
> 
> 
>    # print the list contents
>     print global_filegroup_array[0].mylist
> 
> ------------ end of file
> 
>   Output is:    [u'.string1', u'.string2', u'.string3' ]      # only
> u'string1' should show up
> 
>    No matter which index I use into the global array, I always get ALL of
> the strings
>    showing up. I should only get  u'string1' showing up,   and u'string2'
> if
>    I used  "[1].mylist"
> 
> 
> How I resolved it, is by slipping in
> 
>              self.mylist = []
> 
>    before
> 
>       put_stuff_in_my_list(anyfile)
> 
>  in   __init__(self)
> 
> Why should I have to empty out the list when it's a member of a newly
> instantiated object?

Because __init__() is called when a class is about to be instantiated.  You are
masking the *class variable* mylist with a local *instance variable* of the
same name.  The latter is not shared amongst all instances of the class, but
remains unique to the particular instance.

Hope this helps,

/Troels Therkelsen



More information about the Python-list mailing list