这个Python"静态变量"黑客可以使用吗?

aba*_*ter 7 python static

一个经常被问到的问题是Python中的函数内部是否存在静态变量.有许多答案,例如使用嵌套函数,装饰器等创建包装类.

我找到的最优雅的解决方案之一就是这个,我稍作修改:

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
    .....
    .....
Run Code Online (Sandbox Code Playgroud)

例:

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)
Run Code Online (Sandbox Code Playgroud)

产量

$ python static.py
0
1
3
6
10
15
21
28
36
45
Run Code Online (Sandbox Code Playgroud)

有什么理由我应该避免这种方法吗?无论如何,它是如何工作的?

Sea*_*ira 2

这是如何运作的?

它之所以有效,是因为该函数的名称只是本地作用域中的另一个条目,并且该函数是一个像 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
Run Code Online (Sandbox Code Playgroud)

  • @abalter:它必须在范围内。否则递归将不起作用。 (3认同)
  • `def foo` 在模块范围内定义名称 `foo`。模块中的所有内容都在函数“foo”的范围内,包括名称“foo”。 (3认同)