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

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

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


当前回答

有点相反,但这应该是有效的:

def foo():
    foo.counter += 1
    print "Counter is %d" % foo.counter
foo.counter = 0

如果你想让计数器初始化代码在顶部而不是底部,你可以创建一个装饰器:

def static_vars(**kwargs):
    def decorate(func):
        for k in kwargs:
            setattr(func, k, kwargs[k])
        return func
    return decorate

然后像这样使用代码:

@static_vars(counter=0)
def foo():
    foo.counter += 1
    print "Counter is %d" % foo.counter

它仍然需要你使用foo。前缀,不幸的是。

(图片来源:@ony)

其他回答

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

使用generator函数生成迭代器。

def foo_gen():
    n = 0
    while True:
        n+=1
        yield n

然后像这样使用它

foo = foo_gen().next
for i in range(0,10):
    print foo()

如果你想要一个上限:

def foo_gen(limit=100000):
    n = 0
    while n < limit:
       n+=1
       yield n

如果迭代器终止(如上面的例子),您也可以直接遍历它,如

for i in foo_gen(20):
    print i

当然,在这些简单的情况下,最好使用xrange:)

这是yield statement的文档。

其他解决方案将计数器属性附加到函数,通常使用复杂的逻辑来处理初始化。这对于新代码是不合适的。

在Python 3中,正确的方法是使用非局部语句:

counter = 0
def foo():
    nonlocal counter
    counter += 1
    print(f'counter is {counter}')

有关非局部语句的规范,请参阅PEP 3104。

如果计数器是模块私有的,则应该将其命名为_counter。

惯用的方法是使用类,类可以有属性。如果您需要实例不分离,请使用单例。

有许多方法可以将“静态”变量伪造或蒙骗到Python中(到目前为止没有提到的一种方法是使用可变的默认参数),但这不是Python的惯用方法。只需要使用一个类。

如果您的使用模式合适,也可以使用生成器。

这个回答建立在@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