在C ++中,我们有静态关键字,其中in循环是这样的:
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
初始化一次。我怎样才能在python 3.x中做同样的事情?
答案 0 :(得分:21)
假设你想要的是&#34;一个在第一次函数调用时只初始化一次的变量&#34;,在Python语法中没有这样的东西。但是有很多方法可以获得类似的结果:
1 - 使用全局。请注意,在Python中,&#39; global&#39;对于模块来说真的意味着全球化,而不是全球化的过程&#39;:
_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 bis - 使用class属性和元类
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 - 制作&#34;创意&#34;使用函数的默认参数仅在模块导入时实例化一次:
def yourfunc(x, y, _hack=[0]):
for i in range(x):
for j in range(y):
_hack[0] += 1
还有一些其他可能的解决方案/黑客攻击,但我认为你现在可以了解全局。
编辑:给出了操作的澄清,即&#34;让我们说你有一个带有默认参数的递归函数,但是如果有人真的试图再为你的函数提供一个参数,那么它可能是灾难性的&#34;,它看起来像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)
其中,BTW,证明我们真的有另一个XY问题......
答案 1 :(得分:5)
Python没有静态变量by design。对于您的示例,并且通常在循环块等中使用,您只需在外部作用域中使用变量;如果这使得它太长寿,可能是时候考虑将该功能分解为较小的功能。
对于在函数调用之间继续存在的变量,这只是重新实现对象的基本思想和该对象的方法,所以你应该改为其中之一。
答案 2 :(得分:4)
您可以使用nonlocal
创建一个闭包以使其可编辑(仅限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)
答案 3 :(得分:1)
您还可以使用global关键字:
def main(args):
for i in xrange(10):
print i
global tmp
tmp = i
但要小心......在大多数情况下,它会增加比解决的问题更多的问题。
答案 4 :(得分:0)
在python中执行此操作的另一种基于函数的方法是:
def f(arg, static_var=[0]):
static_var[0] += arg
当static_var
对象在函数定义中初始化,然后重用于所有调用时,它将像静态变量一样运行。请注意,您不能只使用int
,因为它们是不可变的。
>>> def f(arg, static_var=[0]):
... static_var[0] += arg
... print(static_var[0])
...
>>> f(1)
1
>>> f(2)
3
>>> f(3)
6
答案 5 :(得分:0)
使用defaultdict
:
from collections import defaultdict
static = defaultdict(lambda: 0)
def myfunc():
for x in range(10):
for y in range(10):
static['number_of_times'] += 1