What is the idiomatic Python equivalent of this C/C++ code?
void foo()
{
static int counter = 0;
counter++;
Here is a fully encapsulated version that doesn't require an external initialization call:
def fn():
fn.counter=vars(fn).setdefault('counter',-1)
fn.counter+=1
print (fn.counter)
In Python, functions are objects and we can simply add, or monkey patch, member variables to them via the special attribute __dict__
. The built-in vars()
returns the special attribute __dict__
.
EDIT: Note, unlike the alternative try:except AttributeError
answer, with this approach the variable will always be ready for the code logic following initialization. I think the try:except AttributeError
alternative to the following will be less DRY and/or have awkward flow:
def Fibonacci(n):
if n<2: return n
Fibonacci.memo=vars(Fibonacci).setdefault('memo',{}) # use static variable to hold a results cache
return Fibonacci.memo.setdefault(n,Fibonacci(n-1)+Fibonacci(n-2)) # lookup result in cache, if not available then calculate and store it
EDIT2: I only recommend the above approach when the function will be called from multiple locations. If instead the function is only called in one place, it's better to use nonlocal
:
def TheOnlyPlaceStaticFunctionIsCalled():
memo={}
def Fibonacci(n):
nonlocal memo # required in Python3. Python2 can see memo
if n<2: return n
return memo.setdefault(n,Fibonacci(n-1)+Fibonacci(n-2))
...
print (Fibonacci(200))
...
A global declaration provides this functionality. In the example below (python 3.5 or greater to use the "f"), the counter variable is defined outside of the function. Defining it as global in the function signifies that the "global" version outside of the function should be made available to the function. So each time the function runs, it modifies the value outside the function, preserving it beyond the function.
counter = 0
def foo():
global counter
counter += 1
print("counter is {}".format(counter))
foo() #output: "counter is 1"
foo() #output: "counter is 2"
foo() #output: "counter is 3"