使用类时,我可以使用属性保留状态:
class Hello:
def __init__(self):
self.hello = 1
def add_one(self):
if self.hello < 3:
self.hello += 1
else:
self.hello = 1
h = Hello()
for _ in range(5):
h.add_one()
print(h.hello)
# output
2
3
1
2
3
在调用
h.add_one()
之间,状态保存在 h.hello
中。
函数中是否有等效的机制?类似的东西
def add_one():
a_special_kind_of_variable_which_is_not_reinitialized hello
if hello_is_not_initialized:
hello = 1
if hello < 3:
hello += 1
else:
hello = 1
return hello
for _ in range(5):
print(add_one())
# same output as above
Python 没有 C 风格的静态变量。但是,您可以使用闭包来模拟它们。
def make_add_one():
x = 0
def _():
nonlocal x
if x < 3:
x += 1
else:
x = 1
return x
return _
add_one = make_add_one()
for _ in range(5):
print(add_one())
对象(数据与函数)和闭包(函数与数据)之间存在二元性;与 Carcigenicate 定义的 类相比(稍作修改):
class AddOne:
def __init__(self):
self.hello = 0
def __call__(self):
if self.hello < 3:
self.hello += 1
else:
self.hello = 1
return self.hello
add_one = AddOne()
for _ in range(5):
print(add_one())
可以看到以下对应关系:
AddOne
↔ 外部函数 make_add_one
AddOne()
↔ 内部函数 make_add_one()
AddOne().hello
↔ 非局部变量 hello
内部 make_add_one
__call__
: 来使类的实例类似于函数
class Hello:
def __init__(self):
self.hello = 1
def __call__(self):
if self.hello < 3:
self.hello += 1
else:
self.hello = 1
h = Hello()
h() # Works now
尽管如此,这只改变了调用语法。这基本上仍然是您的一流示例。
无论如何,拥有“函数实例”可能是一个更安全的设置。测试一个不具有来自对其执行的其他操作的永久持久状态的函数会更容易。为了干净地测试它,您只需要创建一个新实例,而使用“全局函数”,它可能会意外地受到您之前对其所做的其他操作的影响。
您可以向函数添加属性,因为它们是对象:
def add_one():
if not hasattr(add_one, 'hello'):
add_one.hello = 1
if add_one.hello < 3:
add_one.hello += 1
else:
add_one.hello = 1
return add_one.hello
for _ in range(5):
print(add_one())
输出
2
3
1
2
3