From: kj on 1 Apr 2010 18:34 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. 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.) Another approach would be to stuff the static values in the function's __dict__. This is less satisfactory than the closure approach because the "pseudo-static" variable is accessible from outside the function, but the code is arguably a little more straightforward, and one does not end up with the now useless one-time closure-generating function kicking around. Here's another version of the function above: >>> def spam(): .... d = spam.__dict__ .... if not 's' in spam.__dict__: .... spam.s = 1 .... print spam.s .... spam.s += 1 .... >>> spam() 1 >>> spam() 2 >>> spam() 3 Besides the external accessibility issue, I don't like explictly coding the name of the function within the function. Is there any way to have the function access its own __dict__ without having to explicitly code its name in its body? E.g., is there some generic special variable that, within a function, refers to the function object itself? I'm sure that there are many other ways to skin this cat, especially if one starts definining fancy callable classes and whatnot. But is there a better *simple* way to achieve C-style static locals in Python that does not require a lot of extra machinery? TIA! ~K
From: Chris Rebert on 1 Apr 2010 18:51 On Thu, Apr 1, 2010 at 3:34 PM, kj <no.email(a)please.post> wrote: > When coding C I have often found static local variables useful for > doing once-only run-time initializations. <snip> > Another approach would be to stuff the static values in the function's > __dict__. Â This is less satisfactory than the closure approach > because the "pseudo-static" variable is accessible from outside > the function, but the code is arguably a little more straightforward, > and one does not end up with the now useless one-time closure-generating > function kicking around. Â Here's another version of the function > above: > >>>> def spam(): > ... Â Â d = spam.__dict__ > ... Â Â if not 's' in spam.__dict__: > ... Â Â Â Â spam.s = 1 > ... Â Â print spam.s > ... Â Â spam.s += 1 > ... >>>> spam() > 1 >>>> spam() > 2 >>>> spam() > 3 > > Besides the external accessibility issue, I don't like explictly > coding the name of the function within the function. Â Is there any > way to have the function access its own __dict__ without having to > explicitly code its name in its body? Â E.g., is there some generic > special variable that, within a function, refers to the function > object itself? Nope. It's been proposed in that past (http://www.python.org/dev/peps/pep-3130/), but that proposal was rejected. > I'm sure that there are many other ways to skin this cat, especially > if one starts definining fancy callable classes and whatnot. Â But > is there a better *simple* way to achieve C-style static locals in > Python that does not require a lot of extra machinery? You can abuse the default argument value mechanism: def spam(s_cell=[1]): s = s_cell[0] print s s_cell[0] += 1 It's a bit less ugly when the value itself is mutable, which isn't the case here with the integer. Personally, I hate such abuse with a passion; I think a global variable is clearest. Cheers, Chris -- http://blog.rebertia.com
From: Steve Holden on 1 Apr 2010 19:10 Chris Rebert wrote: > On Thu, Apr 1, 2010 at 3:34 PM, kj <no.email(a)please.post> wrote: >> When coding C I have often found static local variables useful for >> doing once-only run-time initializations. > <snip> >> Another approach would be to stuff the static values in the function's >> __dict__. This is less satisfactory than the closure approach >> because the "pseudo-static" variable is accessible from outside >> the function, but the code is arguably a little more straightforward, >> and one does not end up with the now useless one-time closure-generating >> function kicking around. Here's another version of the function >> above: >> >>>>> def spam(): >> ... d = spam.__dict__ >> ... if not 's' in spam.__dict__: >> ... spam.s = 1 >> ... print spam.s >> ... spam.s += 1 >> ... >>>>> spam() >> 1 >>>>> spam() >> 2 >>>>> spam() >> 3 >> >> Besides the external accessibility issue, I don't like explictly >> coding the name of the function within the function. Is there any >> way to have the function access its own __dict__ without having to >> explicitly code its name in its body? E.g., is there some generic >> special variable that, within a function, refers to the function >> object itself? > > Nope. It's been proposed in that past > (http://www.python.org/dev/peps/pep-3130/), but that proposal was > rejected. > >> I'm sure that there are many other ways to skin this cat, especially >> if one starts definining fancy callable classes and whatnot. But >> is there a better *simple* way to achieve C-style static locals in >> Python that does not require a lot of extra machinery? > > You can abuse the default argument value mechanism: > > def spam(s_cell=[1]): > s = s_cell[0] > print s > s_cell[0] += 1 > > It's a bit less ugly when the value itself is mutable, which isn't the > case here with the integer. > > Personally, I hate such abuse with a passion; I think a global > variable is clearest. But the real problem is that the OP is insisting on using purely procedural Python when the problem is screaming for an object-oriented answer. If the function were instead a method then the instance namespace would be the logical place to store the required data. regards Steve regards Steve -- Steve Holden +1 571 484 6266 +1 800 494 3119 See PyCon Talks from Atlanta 2010 http://pycon.blip.tv/ Holden Web LLC http://www.holdenweb.com/ UPCOMING EVENTS: http://holdenweb.eventbrite.com/
From: Terry Reedy on 1 Apr 2010 19:28 On 4/1/2010 6:34 PM, kj wrote: > > > 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); Global var or class or closure such as below (obviously untested ;=): make_foo() mongo = heavy_lifting_at_runtime(); def _(x,y,z): return frobnicate(mongo, x, y, z) return _ foo = make_foo del make_foo # to make sure it is *never* called again ; Now you only have foo with a hard-to-access private object and no first_time checks when you call it. Terry Jan Reedy
From: Patrick Maupin on 1 Apr 2010 19:30
On Apr 1, 6:10 pm, Steve Holden <st...(a)holdenweb.com> wrote: > Chris Rebert wrote: > > Personally, I hate such abuse with a passion; I think a global > > variable is clearest. > > But the real problem is that the OP is insisting on using purely > procedural Python when the problem is screaming for an object-oriented > answer. > > If the function were instead a method then the instance namespace would > be the logical place to store the required data. In some situations I will use either the default parameter initialization Chris mentioned, or the closure mechanism that the OP presented, but only on code that I am optimizing for speed (local variable lookups, even in nested functions, being much faster than global or instance lookups). If it doesn't need to go fast, globals or instance variables are the way to go. Pat |