views:

516

answers:

3

While answering http://stackoverflow.com/questions/68645/python-static-variable#81002

I noticed that PythonWin PyWin32 build 209.2 interpreter seems to evaluate twice?

PythonWin 2.5 (r25:51908, Mar  9 2007, 17:40:28) [MSC v.1310 32 bit (Intel)] on win32.
Portions Copyright 1994-2006 Mark Hammond - see 'Help/About PythonWin' for further copyright information.
>>> class X:
...     l = []
...     def __init__(self):
...      self.__class__.l.append(1)
...      
>>> X().l
[1, 1]
>>>

while the python interpreter does the right thing

C:\>python
ActivePython 2.5.0.0 (ActiveState Software Inc.) based on
Python 2.5 (r25:51908, Mar  9 2007, 17:40:28) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> class X:
...   l = []
...   def __init__(self):
...     self.__class__.l.append(1)
...
>>> X().l
[1]
>>>
+3  A: 

My guess is as follows. The PythonWin editor offers autocomplete for an object, i.e. when you type myobject. it offers a little popup of all the availble method names. So I think when you type X(). it's creating an instance of X in the background and doing a dir or similar to find out the attributes of the object.

So the constructor is only being run once for each object but to give you the interactivity it's creating objects silently in the background without telling you about it.

Dave Webb
+1  A: 

Two small additional points.

First, self.__class__.l.append(1) isn't really sensible.

Just say self.l.append(1). Python searches the instance before it searches the class for the reference.

More importantly, class-level variables are rarely useful. Class-level constants are sometimes sensible, but even then, they're hard to justify.

In C++ and Java, class-level ('static') variables seem handy, but don't do much of value. They're hard to teach to n00bz -- often wasting lots of classroom time on minutia -- and they aren't very practical. If you want to know all instances of an X that was created, it's probably better to create an XFactory class that doesn't rely on class variables.

class XFactory( object ):
    def __init__( self ):
        self.listOfX= []
    def makeX( self, *args, **kw ):
        newX= X(*args,**kw)
        self.listOfX.append(newX)
        return newX

No class-level variable anomalies. And, it doesn't conflate the X's with the collection of X's. In the long run, I find it confusing when a class is both some thing and also some collection of things.

Simpler is better than Complex.

S.Lott
If you look at my post I was answering the static question attached. So I want to specifically change the class variable and not the instance variable. The code I wrote is the "cleanest" way to explicitly access class variables.
Gregory
+2  A: 

Dave Webb is correct, and you can see this by adding a print statement:

>>> class X:
...     l = []
...     def __init__(self):
...             print 'inited'
...             self.__class__.l.append(1)
...

Then as soon as you type the period in X(). it prints inited prior to offering you the completion popup.

Bill Barksdale