Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static variable in Python?

In C++ we have static keyword which in loops is something like this:

for(int x=0; x<10; x++)
    {
      for(int y=0; y<10; y++)
      {
        static int number_of_times = 0;
        number_of_times++;
      }
    }

static here makes number_of_times initialized once. How can I do same thing in python 3.x?

EDIT: Since most of the people got confused I would like to point out that the code I gave is just example of static usage in C++. My real problem is that I want to initialize only ONE time variable in function since I dont want it to be global(blah!) or default parameter..

like image 801
kuskmen Avatar asked Oct 29 '14 12:10

kuskmen


People also ask

Are there static variables in python?

Python does not have a 'static' keyword to declare the static variable. In Python, you simply declare a variable inside the class, note that it should not be inside any method, and that variable will be known as a static or class variable.

What is static variable with example?

1) A static int variable remains in memory while the program is running. A normal or auto variable is destroyed when a function call where the variable was declared is over. For example, we can use static int to count a number of times a function is called, but an auto variable can't be used for this purpose.

How do you keep a variable static in python?

A way to keep the static variables in sync is to make them properties: class Test(object): , _i = 3 , @property , def i(self) , return type(self).

What is a static variable in?

Static Variables: When a variable is declared as static, then a single copy of the variable is created and shared among all objects at a class level. Static variables are, essentially, global variables. All instances of the class share the same static variable.


1 Answers

Assuming what you want is "a variable that is initialised only once on first function call", there's no such thing in Python syntax. But there are ways to get a similar result:

1 - Use a global. Note that in Python, 'global' really means 'global to the module', not 'global to the process':

_number_of_times = 0

def yourfunc(x, y):
    global _number_of_times
    for i in range(x):
        for j in range(y):
            _number_of_times += 1

2 - Wrap you code in a class and use a class attribute (ie: an attribute that is shared by all instances). :

class Foo(object):
    _number_of_times = 0

    @classmethod
    def yourfunc(cls, x, y):
        for i in range(x):
            for j in range(y):
                cls._number_of_times += 1

Note that I used a classmethod since this code snippet doesn't need anything from an instance

3 - Wrap you code in a class, use an instance attribute and provide a shortcut for the method:

class Foo(object):
    def __init__(self):
         self._number_of_times = 0

    def yourfunc(self, x, y):
        for i in range(x):
            for j in range(y):
                self._number_of_times += 1

yourfunc = Foo().yourfunc

4 - Write a callable class and provide a shortcut:

class Foo(object):
    def __init__(self):
         self._number_of_times = 0

    def __call__(self, x, y):
        for i in range(x):
            for j in range(y):
                self._number_of_times += 1


yourfunc = Foo()

4 bis - use a class attribute and a metaclass

class Callable(type):
    def __call__(self, *args, **kw):
        return self._call(*args, **kw)

class yourfunc(object):
    __metaclass__ = Callable

    _numer_of_times = 0

    @classmethod
    def _call(cls, x, y):
        for i in range(x):
            for j in range(y):                 
                cls._number_of_time += 1

5 - Make a "creative" use of function's default arguments being instantiated only once on module import:

def yourfunc(x, y, _hack=[0]):
    for i in range(x):
        for j in range(y):
            _hack[0] += 1

There are still some other possible solutions / hacks, but I think you get the big picture now.

EDIT: given the op's clarifications, ie "Lets say you have a recursive function with default parameter but if someone actually tries to give one more argument to your function it could be catastrophic", it looks like what the OP really wants is something like:

# private recursive function using a default param the caller shouldn't set
def _walk(tree, callback, level=0):
    callback(tree, level)
    for child in tree.children:
        _walk(child, callback, level+1):

# public wrapper without the default param
def walk(tree, callback):
    _walk(tree, callback)

Which, BTW, prove we really had Yet Another XY Problem...

like image 110
bruno desthuilliers Avatar answered Sep 26 '22 13:09

bruno desthuilliers