这个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);
}
具体来说,如何在函数级别实现静态成员,而不是在类级别?将函数放入类中会改变什么吗?
当前回答
根据丹尼尔的回答(补充):
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化。
其他回答
根据丹尼尔的回答(补充):
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化。
有点相反,但这应该是有效的:
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 foo():
try:
foo.counter += 1
except AttributeError:
foo.counter = 1
推理:
非常python化(“请求原谅而不是允许”) 使用异常(只抛出一次)而不是if分支(考虑StopIteration异常)
你可以创建一个所谓的“函数对象”,并给它一个标准的(非静态的)成员变量,而不是创建一个具有静态局部变量的函数。
既然你给出了一个c++编写的例子,我将首先解释什么是c++中的“函数对象”。“函数对象”就是任何带有重载操作符()的类。类实例的行为类似于函数。例如,你可以写int x = square(5);即使square是一个对象(带有重载操作符()),从技术上讲也不是一个“函数”。你可以给一个函数对象任何你可以给一个类对象的特性。
# C++ function object
class Foo_class {
private:
int counter;
public:
Foo_class() {
counter = 0;
}
void operator() () {
counter++;
printf("counter is %d\n", counter);
}
};
Foo_class foo;
在Python中,我们也可以重载operator(),除非该方法被命名为__call__:
下面是一个类定义:
class Foo_class:
def __init__(self): # __init__ is similair to a C++ class constructor
self.counter = 0
# self.counter is like a static member
# variable of a function named "foo"
def __call__(self): # overload operator()
self.counter += 1
print("counter is %d" % self.counter);
foo = Foo_class() # call the constructor
下面是一个使用这个类的例子:
from foo import foo
for i in range(0, 5):
foo() # function call
打印到控制台的输出是:
counter is 1
counter is 2
counter is 3
counter is 4
counter is 5
如果你想让你的函数接受输入参数,你也可以将它们添加到__call__:
# FILE: foo.py - - - - - - - - - - - - - - - - - - - - - - - - -
class Foo_class:
def __init__(self):
self.counter = 0
def __call__(self, x, y, z): # overload operator()
self.counter += 1
print("counter is %d" % self.counter);
print("x, y, z, are %d, %d, %d" % (x, y, z));
foo = Foo_class() # call the constructor
# FILE: main.py - - - - - - - - - - - - - - - - - - - - - - - - - - - -
from foo import foo
for i in range(0, 5):
foo(7, 8, 9) # function call
# Console Output - - - - - - - - - - - - - - - - - - - - - - - - - -
counter is 1
x, y, z, are 7, 8, 9
counter is 2
x, y, z, are 7, 8, 9
counter is 3
x, y, z, are 7, 8, 9
counter is 4
x, y, z, are 7, 8, 9
counter is 5
x, y, z, are 7, 8, 9
许多人已经建议测试“hasattr”,但有一个更简单的答案:
def func():
func.counter = getattr(func, 'counter', 0) + 1
没有try/except,没有测试hasattr,只有默认的getattr。