Saqib Ali wrote: > I have written two EXTREMELY simple python classes. One class > (myClass1) contains a data attribute (myNum) that contains an integer. > The other class (myClass2) contains a data attribute (mySet) that > contains a set. > > I instantiate 2 instances of myClass1 (a & b). I then change the value > of a.myNum. It works as expected. > > Then I instantiate 2 instances of myClass2 (c & d). I then change the > value of c.mySet. Bizarrely changing the value of c.mySet also affects > the value of d.mySet which I haven't touched at all!?!?!
But that is wrong -- you HAVE touched it. Look carefully: in myClass2, you have this: class myClass2: mySet = sets.Set(range(1,10)) def clearSet(self): self.mySet.clear() mySet is a class attribute, shared by ALL instances, and mySet.clear() modifies it in place. This is exactly the same as this snippet: >>> a = set([1, 2, 3]) >>> b = a >>> b.clear() >>> a set([]) >>> b set([]) In Python, attributes assigned in the class scope are shared between all instances. Attributes assigned directly on self are not: class Test: a = set([1, 2, 3]) def __init__(self): self.b = set([1, 2, 3]) >>> x = Test() >>> y = Test() >>> x.a is y.a # The same set is shared by both instances. True >>> x.b is y.b # Each instance gets its own set. False So why does myClass1 behave differently? Simple: look at the clear method: class myClass1: myNum = 9 def clearNum(self): self.myNum = 0 It assigns a new attribute, rather than modifying the object in place! Assignment to self.myNum creates a new unshared attribute: >>> z = myClass1() >>> z.myNum 9 >>> z.__dict__ # No instance attributes yet. {} >>> z.clearNum() >>> z.__dict__ # Now there is one. {'myNum': 0} >>> z.__class__.myNum # the class attribute still exists 9 The simplest way to fix this is to move the declaration of self.mySet into the __init__ method. -- Steven -- http://mail.python.org/mailman/listinfo/python-list