簡體   English   中英

Python Decorator函數中的靜態變量

[英]static variable in a function with Python Decorator

我一直在尋找Python中的靜態值。

我找到了這個

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 decorator作為靜態變量。

裝飾器(static_var)在返回裝飾的函數(foo)之前初始化靜態值(foo.counter)

所以我認為它不應該按預期工作,因為每次調用foo時,decorator (static_var)初始化foo.counter

因此,我認為,如果FOO()被調用兩次,它應該打印1兩次

foo()     
foo()     

但它打印12 ,增加了foo.counter

為什么...?

為什么每次調用foo時foo.counter都不會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()逐步執行它import pdb; pdb.set_trace() import pdb; pdb.set_trace()

裝飾器包裝其他功能可能會改變它們或返回新功能或兩者兼而有之。

請參閱: 通過12個簡單步驟了解Python裝飾器

如果我們在裝飾器中粘貼一些print會發生什么:

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

正如我上面所說; 首先static_var("counter", 0) ; 然后返回那個( 返回一個函數 )用foo調用,因為它的第一個參數設置了初始的“計數器”並返回相同的參數( 函數foo )。

“foo.counter每次調用foo時都會初始化為0?”

簡短的回答:不, foo.counter設置為0,只有當static_var被調用。

我想也許你對裝飾器和函數裝飾器的創建很少混淆。

@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。

你看到的行為是正確的。 裝飾器僅在聲明時執行一次,而不是在每次調用裝飾函數時執行。 因此foo.counter只初始化為0一次。

想想靜態變量是什么。 通常(例如在C中)它是函數的局部變量,它在函數調用期間持續存在。 通過使用一個名為static_var的裝飾器,可以實現相同的static_var ,因此每次調用foo()foo.counter都會遞增,而不會重置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM