假设你想要的是“一个在第一次函数调用时只初始化一次的变量”,那么 Python 语法中没有这样的东西。但是有一些方法可以获得类似的结果:
1 - 使用全局。请注意,在 Python 中,“全局”实际上意味着“模块全局”,而不是“进程全局”:
_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,因为这段代码 sn-p 不需要实例中的任何内容
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 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 真正想要的是类似:
# 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 问题...