这个C/ c++代码在Python中的等效代码是什么?

void foo()
{
    static int counter = 0;
    counter++;
    printf("counter is %d\n", counter);
}

具体来说,如何在函数级别实现静态成员,而不是在类级别?将函数放入类中会改变什么吗?


当前回答

我写了一个简单的函数来使用静态变量:

def Static():
    ### get the func object by which Static() is called.
    from inspect import currentframe, getframeinfo
    caller = currentframe().f_back
    func_name = getframeinfo(caller)[2]
    # print(func_name)
    caller = caller.f_back
    func = caller.f_locals.get(
        func_name, caller.f_globals.get(
            func_name
        )
    )
    
    class StaticVars:
        def has(self, varName):
            return hasattr(self, varName)
        def declare(self, varName, value):
            if not self.has(varName):
                setattr(self, varName, value)

    if hasattr(func, "staticVars"):
        return func.staticVars
    else:
        # add an attribute to func
        func.staticVars = StaticVars()
        return func.staticVars

使用方法:

def myfunc(arg):
    if Static().has('test1'):
        Static().test += 1
    else:
        Static().test = 1
    print(Static().test)

    # declare() only takes effect in the first time for each static variable.
    Static().declare('test2', 1)
    print(Static().test2)
    Static().test2 += 1

其他回答

def staticvariables(**variables):
    def decorate(function):
        for variable in variables:
            setattr(function, variable, variables[variable])
        return function
    return decorate

@staticvariables(counter=0, bar=1)
def foo():
    print(foo.counter)
    print(foo.bar)

就像上面vincent的代码一样,这将被用作函数装饰器,静态变量必须以函数名作为前缀访问。这段代码的优点(尽管每个人都可以聪明地看出这一点)是你可以有多个静态变量,并以更常规的方式初始化它们。

根据丹尼尔的回答(补充):

class Foo(object): 
    counter = 0  

def __call__(self, inc_value=0):
    Foo.counter += inc_value
    return Foo.counter

foo = Foo()

def use_foo(x,y):
    if(x==5):
        foo(2)
    elif(y==7):
        foo(3)
    if(foo() == 10):
        print("yello")


use_foo(5,1)
use_foo(5,1)
use_foo(1,7)
use_foo(1,7)
use_foo(1,1)

我想添加这一部分的原因是,静态变量不仅用于增加某个值,而且还用于检查静态变量是否等于某个值,作为一个现实生活中的例子。

静态变量仍然受到保护,并且仅在函数use_foo()的作用域内使用。

在这个例子中,调用foo()函数完全是(相对于相应的c++等效函数):

stat_c +=9; // in c++
foo(9)  #python equiv

if(stat_c==10){ //do something}  // c++

if(foo() == 10):      # python equiv
  #add code here      # python equiv       

Output :
yello
yello

如果类Foo被严格定义为一个单例类,那将是理想的。这将使它更加python化。

Python方法中的静态变量

class Count:
    def foo(self):
        try: 
            self.foo.__func__.counter += 1
        except AttributeError: 
            self.foo.__func__.counter = 1

        print self.foo.__func__.counter

m = Count()
m.foo()       # 1
m.foo()       # 2
m.foo()       # 3

使用装饰器和闭包

下面的装饰器可用于创建静态函数变量。它将声明的函数替换为函数本身的返回值。这意味着被修饰的函数必须返回一个函数。

def static_inner_self(func):
    return func()

然后在返回另一个带有捕获变量的函数的函数上使用decorator:

@static_inner_self
def foo():
    counter = 0
    def foo():
        nonlocal counter
        counter += 1
        print(f"counter is {counter}")
    return foo

nonlocal是必需的,否则Python认为计数器变量是一个局部变量而不是一个捕获变量。Python之所以如此,是因为变量赋值counter += 1。函数中的任何赋值都会使Python认为该变量是局部变量。

如果你没有在内部函数中为变量赋值,那么你可以忽略非局部语句,例如,在这个函数中,我用来缩进字符串的行,在这个函数中,Python可以推断出变量是非局部的:

@static_inner_self
def indent_lines():
    import re
    re_start_line = re.compile(r'^', flags=re.MULTILINE)
    def indent_lines(text, indent=2):
        return re_start_line.sub(" "*indent, text)
    return indent_lines

附注:有一个被删除的答案提出了同样的问题。我不知道作者为什么删掉它。 https://stackoverflow.com/a/23366737/195417

_counter = 0
def foo():
   global _counter
   _counter += 1
   print 'counter is', _counter

Python习惯上使用下划线来表示私有变量。在C语言中,在函数内部声明静态变量的唯一原因是将它隐藏在函数之外,这并不是真正的Python惯用方法。