一个经常被问到的问题是在 Python 中函数内部是否有一个等价于静态变量的东西。答案有很多,比如创建包装类、使用嵌套函数、装饰器等。
我找到的最优雅的解决方案之一是 this ,我稍作修改:
def foo():
# see if foo.counter already exists
try: test = foo.counter
# if not, initialize it to whatever
except AttributeError: foo.counter = 0
# do stuff with foo.counter
.....
.....
例子:
static.py
def foo(x):
# see if foo.counter already exists
try: test = foo.counter
# if not, initialize it to whatever
except AttributeError: foo.counter = 0
foo.counter += x
print(foo.counter)
for i in range(10):
foo(i)
输出
$ python static.py
0
1
3
6
10
15
21
28
36
45
有什么理由我应该避免这种方法吗?它到底是如何工作的?
这是如何运作的?
它有效因为函数的名称只是局部作用域中的另一个条目,并且函数是一个对象,就像 Python 中的其他所有对象一样,并且可以在其上设置任意属性:
def foo():
# The foo function object has already been fully constructed
# by the time we get into our `try`
try: test = foo.counter # Only run when foo is invoked
except AttributeError: foo.counter = 0
foo.counter += 1
if hasattr(foo, 'counter'):
print('Foo has a counter attribute')
else:
# This prints out - we've parsed `foo` but not executed it yet
print('Foo.counter does not exist yet')
# Now, we invoke foo
foo()
if hasattr(foo, 'counter'):
# And from now on (until we remove the attribute)
# this test will always succeed because we've added the counter
# attribute to the function foo.
print('Foo has a counter attribute')
else:
print('Foo.counter does not exist yet') # No longer true