Python中的静态变量?

2024-04-19 20:39:55 发布

您现在位置:Python中文网/ 问答频道 /正文

<>在C++中,静态关键字在循环中是这样的:

for(int x=0; x<10; x++)
    {
      for(int y=0; y<10; y++)
      {
        static int number_of_times = 0;
        number_of_times++;
      }
    }

这里的static使number_of_times初始化一次。在Python3.x中,我怎样才能做同样的事情?

<>编辑:因为大多数人都感到困惑,我想指出我所给出的代码只是C++中静态用法的一个例子。我真正的问题是我只想在函数中初始化一个时间变量,因为我不希望它是全局的(blah!)或默认参数。。


Tags: of函数代码编辑number用法for静态
3条回答

Python没有静态变量by design。例如,在循环块内使用,一般来说,只需在外部作用域中使用一个变量;如果这使其寿命太长,则可能是时候考虑将该函数分解为更小的函数了。

对于在对函数的调用之间继续存在的变量,这只是重新实现对象和该对象上的方法的基本思想,因此您应该进行这些操作之一。

假设您想要的是“在第一次函数调用时只初始化一次的变量”,那么在Python语法中没有这样的东西。但也有办法得到类似的结果:

1-使用全局。注意,在Python中,“global”真正的意思是“模块的global”,而不是“进程的global”:

_number_of_times = 0

def yourfunc(x, y):
    global _number_of_times
    for i in range(x):
        for j in range(y):
            _number_of_times += 1

2-将代码包装到类中并使用类属性(即:所有实例共享的属性)。以下内容:

class Foo(object):
    _number_of_times = 0

    @classmethod
    def yourfunc(cls, x, y):
        for i in range(x):
            for j in range(y):
                cls._number_of_times += 1

注意,我使用了一个classmethod,因为这个代码片段不需要来自实例的任何东西

3-将代码包装到类中,使用实例属性并为方法提供快捷方式:

class Foo(object):
    def __init__(self):
         self._number_of_times = 0

    def yourfunc(self, x, y):
        for i in range(x):
            for j in range(y):
                self._number_of_times += 1

yourfunc = Foo().yourfunc

4-编写可调用类并提供快捷方式:

class Foo(object):
    def __init__(self):
         self._number_of_times = 0

    def __call__(self, x, y):
        for i in range(x):
            for j in range(y):
                self._number_of_times += 1


yourfunc = Foo()

4之二-使用类属性和元类

class Callable(type):
    def __call__(self, *args, **kw):
        return self._call(*args, **kw)

class yourfunc(object):
    __metaclass__ = Callable

    _numer_of_times = 0

    @classmethod
    def _call(cls, x, y):
        for i in range(x):
            for j in range(y):                 
                cls._number_of_time += 1

5-在模块导入时“创造性地”使用仅实例化一次的函数默认参数:

def yourfunc(x, y, _hack=[0]):
    for i in range(x):
        for j in range(y):
            _hack[0] += 1

还有其他一些可能的解决方案/黑客,但我想你现在已经了解了大局。

编辑:鉴于op的澄清,即“假设你有一个带有默认参数的递归函数,但如果有人真的试图给你的函数再加一个参数,那可能是灾难性的”,看起来op真正想要的是:

# private recursive function using a default param the caller shouldn't set
def _walk(tree, callback, level=0):
    callback(tree, level)
    for child in tree.children:
        _walk(child, callback, level+1):

# public wrapper without the default param
def walk(tree, callback):
    _walk(tree, callback)

顺便说一句,这证明我们确实还有另一个XY问题。。。

您可以使用^{}创建一个闭包,使其可编辑(仅限python 3.x)。下面是一个递归函数的示例,用于计算列表的长度。

def recursive_len(l):
    res = 0
    def inner(l2):
        nonlocal res
        if l2:
            res += 1
            inner(l2[1:])
    inner(l)
    return res

或者,可以为函数本身指定一个属性。使用here中的技巧:

def fn(self):
    self.number_of_times += 1
fn.func_defaults = (fn,)
fn.number_of_times = 0

fn()
fn()
fn()
print (fn.number_of_times)

相关问题 更多 >