Lists are weird when they are instance members
Troels Therkelsen
t_therkelsen at hotmail.com
Sat Jan 3 18:03:58 EST 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