views:

215

answers:

3
class Ball:
  a = []
  def __init__(self):
    pass

  def add(self,thing):
    self.a.append(thing)

  def size(self):
    print len(self.a)

for i in range(3):
  foo = Ball()
  foo.add(1)
  foo.add(2)
  foo.size()

I would expect a return of :

2
2
2

But I get :

2
4
6

Why is this? I've found that by doing a=[] in the init, I can route around this behavior, but I'm less than clear why.

+4  A: 

doh

I just figured out why.

In the above case, the a is a class attribute, not a data attribute - those are shared by all Balls(). Commenting out the a=[] and placing it into the init block means that it's a data attribute instead. (And, I couldn't access it then with foo.a, which I shouldn't do anyhow.) It seems like the class attributes act like static attributes of the class, they're shared by all instances.

Whoa.

One question though : CodeCompletion sucks like this. In the foo class, I can't do self.(variable), because it's not being defined automatically - it's being defined by a function. Can I define a class variable and replace it with a data variable?

Rizwan Kassim
That's probably down to your editor...what editor and platform?
Matthew Schinckel
Code completion is tricky to implement under Python.
Please accept your own answer.
S.Lott
Please ask a new question about the class/instance attribute for code completion.
ddaa
+2  A: 

What you probably want to do is:

class Ball:
  def __init__(self):
    self.a = []

If you use just a = [], it creates a local variable in the __init__ function, which disappears when the function returns. Assigning to self.a makes it an instance variable which is what you're after.

For a semi-related gotcha, see how you can change the value of default parameters for future callers.

Greg Hewgill
+1  A: 

"Can I define a class variable and replace it with a data variable?"

No. They're separate things. A class variable exists precisely once -- in the class.

You could -- to finesse code completion -- start with some class variables and then delete those lines of code after you've written your class. But every time you forget to do that nothing good will happen.

Better is to try a different IDE. Komodo Edit's code completions seem to be sensible.

If you have so many variables with such long names that code completion is actually helpful, perhaps you should make your classes smaller or use shorter names. Seriously.

I find that when you get to a place where code completion is more helpful than annoying, you've exceeded the "keep it all in my brain" complexity threshold. If the class won't fit in my brain, it's too complex.

S.Lott