What is the Python equivalent of static variables inside a function?

前端 未结 26 2792
天命终不由人
天命终不由人 2020-11-22 00:45

What is the idiomatic Python equivalent of this C/C++ code?

void foo()
{
    static int counter = 0;
    counter++;
          


        
26条回答
  •  攒了一身酷
    2020-11-22 01:36

    Instead of creating a function having a static local variable, you can always create what is called a "function object" and give it a standard (non-static) member variable.

    Since you gave an example written C++, I will first explain what a "function object" is in C++. A "function object" is simply any class with an overloaded operator(). Instances of the class will behave like functions. For example, you can write int x = square(5); even if square is an object (with overloaded operator()) and not technically not a "function." You can give a function-object any of the features that you could give a class object.

    # C++ function object
    class Foo_class {
        private:
            int counter;     
        public:
            Foo_class() {
                 counter = 0;
            }
            void operator() () {  
                counter++;
                printf("counter is %d\n", counter);
            }     
       };
       Foo_class foo;
    

    In Python, we can also overload operator() except that the method is instead named __call__:

    Here is a class definition:

    class Foo_class:
        def __init__(self): # __init__ is similair to a C++ class constructor
            self.counter = 0
            # self.counter is like a static member
            # variable of a function named "foo"
        def __call__(self): # overload operator()
            self.counter += 1
            print("counter is %d" % self.counter);
    foo = Foo_class() # call the constructor
    

    Here is an example of the class being used:

    from foo import foo
    
    for i in range(0, 5):
        foo() # function call
    

    The output printed to the console is:

    counter is 1
    counter is 2
    counter is 3
    counter is 4
    counter is 5
    

    If you want your function to take input arguments, you can add those to __call__ as well:

    # FILE: foo.py - - - - - - - - - - - - - - - - - - - - - - - - -
    
    class Foo_class:
        def __init__(self):
            self.counter = 0
        def __call__(self, x, y, z): # overload operator()
            self.counter += 1
            print("counter is %d" % self.counter);
            print("x, y, z, are %d, %d, %d" % (x, y, z));
    foo = Foo_class() # call the constructor
    
    # FILE: main.py - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    
    from foo import foo
    
    for i in range(0, 5):
        foo(7, 8, 9) # function call
    
    # Console Output - - - - - - - - - - - - - - - - - - - - - - - - - - 
    
    counter is 1
    x, y, z, are 7, 8, 9
    counter is 2
    x, y, z, are 7, 8, 9
    counter is 3
    x, y, z, are 7, 8, 9
    counter is 4
    x, y, z, are 7, 8, 9
    counter is 5
    x, y, z, are 7, 8, 9
    

提交回复
热议问题