这个C/ c++代码在Python中的等效代码是什么?
void foo()
{
static int counter = 0;
counter++;
printf("counter is %d\n", counter);
}
具体来说,如何在函数级别实现静态成员,而不是在类级别?将函数放入类中会改变什么吗?
这个C/ c++代码在Python中的等效代码是什么?
void foo()
{
static int counter = 0;
counter++;
printf("counter is %d\n", counter);
}
具体来说,如何在函数级别实现静态成员,而不是在类级别?将函数放入类中会改变什么吗?
当前回答
其他解决方案将计数器属性附加到函数,通常使用复杂的逻辑来处理初始化。这对于新代码是不合适的。
在Python 3中,正确的方法是使用非局部语句:
counter = 0
def foo():
nonlocal counter
counter += 1
print(f'counter is {counter}')
有关非局部语句的规范,请参阅PEP 3104。
如果计数器是模块私有的,则应该将其命名为_counter。
其他回答
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的代码一样,这将被用作函数装饰器,静态变量必须以函数名作为前缀访问。这段代码的优点(尽管每个人都可以聪明地看出这一点)是你可以有多个静态变量,并以更常规的方式初始化它们。
另一个(不推荐!)对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
鉴于这个问题,我可以提出另一个可能更好用的替代方案,对方法和函数看起来都是一样的:
@static_var2('seed',0)
def funccounter(statics, add=1):
statics.seed += add
return statics.seed
print funccounter() #1
print funccounter(add=2) #3
print funccounter() #4
class ACircle(object):
@static_var2('seed',0)
def counter(statics, self, add=1):
statics.seed += add
return statics.seed
c = ACircle()
print c.counter() #1
print c.counter(add=2) #3
print c.counter() #4
d = ACircle()
print d.counter() #5
print d.counter(add=2) #7
print d.counter() #8
如果你喜欢这种用法,下面是它的实现:
class StaticMan(object):
def __init__(self):
self.__dict__['_d'] = {}
def __getattr__(self, name):
return self.__dict__['_d'][name]
def __getitem__(self, name):
return self.__dict__['_d'][name]
def __setattr__(self, name, val):
self.__dict__['_d'][name] = val
def __setitem__(self, name, val):
self.__dict__['_d'][name] = val
def static_var2(name, val):
def decorator(original):
if not hasattr(original, ':staticman'):
def wrapped(*args, **kwargs):
return original(getattr(wrapped, ':staticman'), *args, **kwargs)
setattr(wrapped, ':staticman', StaticMan())
f = wrapped
else:
f = original #already wrapped
getattr(f, ':staticman')[name] = val
return f
return decorator
_counter = 0 def foo(): global _counter _counter += 1 print 'counter is', _counter
Python习惯上使用下划线来表示私有变量。在C语言中,在函数内部声明静态变量的唯一原因是将它隐藏在函数之外,这并不是真正的Python惯用方法。
其他解决方案将计数器属性附加到函数,通常使用复杂的逻辑来处理初始化。这对于新代码是不合适的。
在Python 3中,正确的方法是使用非局部语句:
counter = 0
def foo():
nonlocal counter
counter += 1
print(f'counter is {counter}')
有关非局部语句的规范,请参阅PEP 3104。
如果计数器是模块私有的,则应该将其命名为_counter。