* kj:
When coding C I have often found static local variables useful for
doing once-only run-time initializations.  For example:

int foo(int x, int y, int z) {

  static int first_time = TRUE;
  static Mongo *mongo;
  if (first_time) {
    mongo = heavy_lifting_at_runtime();
    first_time = FALSE;
  }

  return frobnicate(mongo, x, y, z);
}

In this case, the static variable mongo is initialized only once
(at most).

What I like most about this is that it obviates the need for a
global variable to hold the persistent value (I avoid globals like
the plague, especially in Python).  It also nicely encapsulates
the logic that determines whether initialization is required.

In C++ you just write

  int foo( int x, int y, int z )
  {
      static Mongo* const mongo = heavy_lifting_at_runtime();
      return frobnicate( mongo, x, y, z );
  }



The best way I've found to achieve a similar effect in (procedural)
Python defines the function as a closure.  For example, here's a
function that keeps track of (and prints out) how many times it
has been called:

def make_spam():
...     counter = [0]
...     def _():
...         counter[0] += 1
...         print counter[0]
...     return _
...
spam = make_spam()
spam()
1
spam()
2
spam()
3

(Too bad that one can't stick the whole def inside parentheses and
call the function right there, like one can do with JavaScript.)

Off the cuff, Py3:

class Spam:
    def __init__( self ):
        self._counter = 0

    def __call__( self ):
        self._counter += 1
        print( counter )

spam = Spam()
spam()
spam()
spam()


[snip]
I'm sure that there are many other ways to skin this cat, especially
if one starts definining fancy callable classes and whatnot.

As I see it it's the closure that's fancy, and the class that's simple and 
direct.


 But
is there a better *simple* way to achieve C-style static locals in
Python that does not require a lot of extra machinery?

If you often need this functionality you might consider a general decorator that supplies the function with a self argument, e.g. like this:


<example>
#Py3

class Object: pass

def static_initialization( init_func ):
    def self_aware( f ):
        def wrapped( *args, **kwargs ):
            return f( f, *args, **kwargs )
        init_func( f )
        return wrapped
    o = Object()
    o.body = self_aware
    return o


# Example usage:

@static_initialization
def spam( self ):
    self.counter = 0

@spam.body
def spam( self ):
    self.counter += 1
    print( self.counter )

spam()
spam()
spam()
</example>


But as mentioned, a class is (at least IMHO) simpler and more direct.



Cheers & hth.,

- Alf (department of disingenious solutions)
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to