Friday, June 24, 2011

Frustrating Python Class Objects

Generally I am a big fan of Python, but today it drove me a little nuts. The solution was hard to find, but simple to implement. And the problem was probably caused by my "Java-thinking," which Pythonic folks will tsk-tsk you for.

What's great about Python is that you can easily distill your problem down to simple parts and test them directly in a script or with the interpreter. So I was able to boil down my problem to the following:



I have the following class defined:

class MyClass:
    my_int = 666
    my_list = []


I then instantiate two copies of the class:

a = MyClass()
b = MyClass()


Then I try to use the members:

a.my_int = 99
a.my_list.append(123)
a.my_list.append(456)


So what do we have when we inspect the contents?

print(a.my_int)
99
print(a.my_list)
[123, 456]
print(b.my_int)
666
print(b.my_list)
[123, 456]


What happened here? The primitive integer worked just like we expected...we set it for each instance and it is set separately. All of the primitive types should do this.

But the list object threw us for a loop...each instance of the class points to the same list object. The list object was instantiated for the class, and each instance of the class points to that list. So when we add to the list in a, we are adding to the list in the class, and b has visibility into that list as well. Not exactly what I was expecting to have happen, but useful in situations where you want a "static" member of the class.

The solution is to define the list in the __init__ constructor function of the class. That way a new list will be created for each instance. So my code changes to be the following:

class MyClass:
    def __init__(self):
        self.my_int = 666
        self.my_list = []


Now when I do my assigning and testing, everything works the way I wanted:

a = MyClass()
b = MyClass()
a.my_int = 99
a.my_list.append(123)
a.my_list.append(456)
print(a.my_int)
99
print(a.my_list)
[123, 456]
print(b.my_int)
666
print(b.my_list)
[]

No comments:

Post a Comment