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

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

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


当前回答

Python没有静态变量,但你可以通过定义一个可调用的类对象,然后将其用作函数来伪装它。也可以看看这个答案。

class Foo(object):
  # Class variable, shared by all instances of this class
  counter = 0

  def __call__(self):
    Foo.counter += 1
    print Foo.counter

# Create an object instance of class "Foo," called "foo"
foo = Foo()

# Make calls to the "__call__" method, via the object's name itself
foo() #prints 1
foo() #prints 2
foo() #prints 3

注意,__call__使类(对象)的实例可以通过自己的名称调用。这就是为什么上面调用foo()会调用类的__call__方法。从文档中可以看到:

任意类的实例都可以通过在类中定义__call__()方法来实现可调用。

其他回答

许多人已经建议测试“hasattr”,但有一个更简单的答案:

def func():
    func.counter = getattr(func, 'counter', 0) + 1

没有try/except,没有测试hasattr,只有默认的getattr。

另一个(不推荐!)对https://stackoverflow.com/a/279598/916373这样的可调用对象的扭曲,如果您不介意使用一个时髦的调用签名的话

class foo(object):
    counter = 0;
    @staticmethod
    def __call__():
        foo.counter += 1
        print "counter is %i" % foo.counter

>>> foo()()
counter is 1
>>> foo()()
counter is 2

您可以向函数添加属性,并将其用作静态变量。

def myfunc():
  myfunc.counter += 1
  print myfunc.counter

# attribute must be initialized
myfunc.counter = 0

或者,如果你不想在函数外部设置变量,你可以使用hasattr()来避免AttributeError异常:

def myfunc():
  if not hasattr(myfunc, "counter"):
     myfunc.counter = 0  # it doesn't exist yet, so initialize it
  myfunc.counter += 1

无论如何,静态变量是相当罕见的,您应该为这个变量找到一个更好的位置,最有可能是在类中。

这个回答建立在@claudiu的回答之上。

我发现我的代码变得越来越不清晰,而我一直都很清楚 当我要访问静态变量时,可以在函数名前面加上。

也就是说,在我的函数代码中,我更喜欢这样写:

print(statics.foo)

而不是

print(my_function_name.foo)

所以,我的解决方案是:

向函数中添加静态属性 在函数作用域中,添加一个局部变量statics作为my_function.statics的别名

from bunch import *

def static_vars(**kwargs):
    def decorate(func):
        statics = Bunch(**kwargs)
        setattr(func, "statics", statics)
        return func
    return decorate

@static_vars(name = "Martin")
def my_function():
    statics = my_function.statics
    print("Hello, {0}".format(statics.name))

备注

我的方法使用一个名为Bunch的类,它是一个字典,支持 属性风格的访问,一种JavaScript(参见2000年左右关于它的原始文章)

它可以通过pip install bunch安装

也可以这样手写:

class Bunch(dict):
    def __init__(self, **kw):
        dict.__init__(self,kw)
        self.__dict__ = self
_counter = 0
def foo():
   global _counter
   _counter += 1
   print 'counter is', _counter

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