带有 Python 装饰器的函数中的静态变量
static variable in a function with Python Decorator
我在 Python 中寻找有关静态值的信息。
我发现 this。
def static_var(varname, value):
def decorate(func):
setattr(func, varname, value)
return func
return decorate
@static_var("counter", 0)
def foo():
foo.counter += 1
print "Counter is %d" % foo.counter
函数中的静态变量使用 python 装饰器。
装饰器(static_var)
在返回函数(foo)
装饰器之前初始化静态值(foo.counter)
。
所以我认为它不应该按预期工作,因为装饰器(static_var)
每次调用foo
时都会初始化foo.counter
。
因此,我认为如果 foo() 被调用两次,它应该打印 1
两次
foo()
foo()
但它打印 1
和 2
,增加 foo.counter
为什么...?
为什么每次调用 foo 时 foo.counter
没有初始化为 0
?
因为:
def static_var(varname, value):
def decorate(func):
setattr(func, varname, value)
return func
return decorate
@static_var("counter", 0)
def foo():
foo.counter += 1
print "Counter is %d" % foo.counter
相当于:
foo = static_var("counter", 0)(foo)
注意到 static_var()
实际上被调用了吗?现在遍历你的装饰器;实际上用 import pdb; pdb.set_trace()
逐步完成它
Decorators wrap other functions potentially either mutating them or
returning new functions or both.
参见:Understanding Python Decorators in 12 easy steps
如果我们在您的装饰器中添加一些 print
(s),观察会发生什么:
def static_var(varname, value):
print "1"
def decorate(func):
print "2"
setattr(func, varname, value)
return func
print "3"
return decorate
@static_var("counter", 0)
def foo():
foo.counter += 1
print "Counter is %d" % foo.counter
foo()
foo()
输出:
$ python foo.py
1
3
2
Counter is 1
Counter is 2
So as I said above; firstly static_var("counter", 0)
is called;
then the return of that (which returns a function) is called with
foo
as it's first argument which sets up the initial "counter" and
returns the same argument (the function foo
).
您看到的行为是正确的。装饰器仅在声明时执行一次,而不是在每次调用装饰函数时执行一次。因此 foo.counter
只被初始化为 0 一次。
想想什么是静态变量。通常(例如在 C 语言中)它是一个函数的局部变量,在对函数的调用中持续存在。通过使用恰当地命名为 static_var
的装饰器,这里实现了相同的效果,因此每次调用 foo()
时 foo.counter
递增而不是重置是有道理的。
"foo.counter initialized to 0 every time when foo is called?"
简短回答:不,foo.counter
仅在调用 static_var
时设置为 0。
我想您可能对装饰器和创建的函数装饰器没有什么混淆。
@decorator
def func():
pass
只是
的语法糖
func = decorator(func)
有了这个,我们就会知道您之前的代码等于:
def foo():
foo.counter += 1
print "Counter is %d" % foo.counter
foo = static_val(foo, "counter", 0)
然后,当您调用 foo()
时,您调用的是新的 foo
函数,而不是 static_val
,其中 counter
属性将被设置为 0。
我在 Python 中寻找有关静态值的信息。
我发现 this。
def static_var(varname, value):
def decorate(func):
setattr(func, varname, value)
return func
return decorate
@static_var("counter", 0)
def foo():
foo.counter += 1
print "Counter is %d" % foo.counter
函数中的静态变量使用 python 装饰器。
装饰器(static_var)
在返回函数(foo)
装饰器之前初始化静态值(foo.counter)
。
所以我认为它不应该按预期工作,因为装饰器(static_var)
每次调用foo
时都会初始化foo.counter
。
因此,我认为如果 foo() 被调用两次,它应该打印 1
两次
foo()
foo()
但它打印 1
和 2
,增加 foo.counter
为什么...?
为什么每次调用 foo 时 foo.counter
没有初始化为 0
?
因为:
def static_var(varname, value):
def decorate(func):
setattr(func, varname, value)
return func
return decorate
@static_var("counter", 0)
def foo():
foo.counter += 1
print "Counter is %d" % foo.counter
相当于:
foo = static_var("counter", 0)(foo)
注意到 static_var()
实际上被调用了吗?现在遍历你的装饰器;实际上用 import pdb; pdb.set_trace()
Decorators wrap other functions potentially either mutating them or returning new functions or both.
参见:Understanding Python Decorators in 12 easy steps
如果我们在您的装饰器中添加一些 print
(s),观察会发生什么:
def static_var(varname, value):
print "1"
def decorate(func):
print "2"
setattr(func, varname, value)
return func
print "3"
return decorate
@static_var("counter", 0)
def foo():
foo.counter += 1
print "Counter is %d" % foo.counter
foo()
foo()
输出:
$ python foo.py
1
3
2
Counter is 1
Counter is 2
So as I said above; firstly
static_var("counter", 0)
is called; then the return of that (which returns a function) is called withfoo
as it's first argument which sets up the initial "counter" and returns the same argument (the functionfoo
).
您看到的行为是正确的。装饰器仅在声明时执行一次,而不是在每次调用装饰函数时执行一次。因此 foo.counter
只被初始化为 0 一次。
想想什么是静态变量。通常(例如在 C 语言中)它是一个函数的局部变量,在对函数的调用中持续存在。通过使用恰当地命名为 static_var
的装饰器,这里实现了相同的效果,因此每次调用 foo()
时 foo.counter
递增而不是重置是有道理的。
"foo.counter initialized to 0 every time when foo is called?"
简短回答:不,foo.counter
仅在调用 static_var
时设置为 0。
我想您可能对装饰器和创建的函数装饰器没有什么混淆。
@decorator
def func():
pass
只是
的语法糖func = decorator(func)
有了这个,我们就会知道您之前的代码等于:
def foo():
foo.counter += 1
print "Counter is %d" % foo.counter
foo = static_val(foo, "counter", 0)
然后,当您调用 foo()
时,您调用的是新的 foo
函数,而不是 static_val
,其中 counter
属性将被设置为 0。