这个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);
}
具体来说,如何在函数级别实现静态成员,而不是在类级别?将函数放入类中会改变什么吗?
当前回答
当然,这是一个老问题,但我想我可以提供一些更新。
看来性能论点已经过时了。 对于siInt_try和isInt_re2,相同的测试套件似乎给出了类似的结果。 当然,结果会有所不同,但这是在我的计算机上使用python 3.4.4的一次会话,使用Xeon W3550的内核4.3.01。 我已经运行了几次,结果似乎相似。 我将全局正则表达式移动到函数静态,但性能差异可以忽略不计。
isInt_try: 0.3690
isInt_str: 0.3981
isInt_re: 0.5870
isInt_re2: 0.3632
考虑到性能问题,try/catch似乎可以生成最适合未来和墙角情况的代码,所以可能只是将其包装在函数中
其他回答
米格尔·安吉洛的自我重新定义解决方案甚至可以不需要任何装饰:
def fun(increment=1):
global fun
counter = 0
def fun(increment=1):
nonlocal counter
counter += increment
print(counter)
fun(increment)
fun() #=> 1
fun() #=> 2
fun(10) #=> 12
第二行必须进行调整,以获得有限的范围:
def outerfun():
def innerfun(increment=1):
nonlocal innerfun
counter = 0
def innerfun(increment=1):
nonlocal counter
counter += increment
print(counter)
innerfun(increment)
innerfun() #=> 1
innerfun() #=> 2
innerfun(10) #=> 12
outerfun()
装饰器的优点是,你不必额外注意你的施工范围。
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
全局声明提供此功能。在下面的例子中(python 3.5或更高版本使用“f”),counter变量在函数外部定义。在函数中将其定义为全局的,意味着函数外部的“全局”版本应该对函数可用。所以每次函数运行时,它都会修改函数外部的值,在函数外部保留它。
counter = 0
def foo():
global counter
counter += 1
print("counter is {}".format(counter))
foo() #output: "counter is 1"
foo() #output: "counter is 2"
foo() #output: "counter is 3"
其他答案已经演示了您应该如何做到这一点。这里有一种方法你不应该:
>>> def foo(counter=[0]):
... counter[0] += 1
... print("Counter is %i." % counter[0]);
...
>>> foo()
Counter is 1.
>>> foo()
Counter is 2.
>>>
默认值仅在函数第一次求值时初始化,而不是每次执行时初始化,因此可以使用列表或任何其他可变对象来存储静态值。
其他解决方案将计数器属性附加到函数,通常使用复杂的逻辑来处理初始化。这对于新代码是不合适的。
在Python 3中,正确的方法是使用非局部语句:
counter = 0
def foo():
nonlocal counter
counter += 1
print(f'counter is {counter}')
有关非局部语句的规范,请参阅PEP 3104。
如果计数器是模块私有的,则应该将其命名为_counter。