Thursday, July 17, 2008

Python class inconsistencies

Update:

Masklinn's correction is obviously correct -- this isn't primarily a class v. instance variable problem, it's the difference between the operators I'm using on the instance variables.

So, an assignment (k.t = ...) points the attribute at a wholly new object, while accessing one of the attributes' methods actually alters the attributes' state.

(Which is where the confusion over mutability comes into play, but it was still confusion on my part.)

My original posting:

This makes a modicum of sense if you have a basic grasp of the distinction between mutables and immutables in Python, but it still seems like a mess.


>>> class K(object):
>>> t = (1,2,3)
>>> l = [1,2,3]
>>>
>>> k = K()
>>> j = K()
>>>
>>> k.t = ('a','b','c')
>>> j.l.append( 10 )
>>>
>>> j.t
(1, 2, 3)
>>> k.l
[1, 2, 3, 10]

Do you see it?

Class K defines two attributes, a tuple t and a list l.

If you instantiate K twice (k and j), then change the t attribute of one and the l attribute of the other, the change to l will be shared between instances, while the change to t will only effect the instance.

Whether an attribute belongs to the class or the instance depends on whether it's type is mutable or not!

There's a fix in one case: you can use __init__ to make mutable data instance-specific:

>>> class K(object):
>>> t = (1,2,3)
>>> l = [1,2,3]
>>> def __init__(self):
>>> self.l = [1,2,3]
Now changes to k.l won't effect j.l

However, I can't find a way to accomplish the opposite--create a class attribute for an immutable data type--w/out resorting to __get_attribute__ magic.